2

假设一个算法有一个策略FooPolicy。实现此策略的策略类具有静态成员函数foo,但对于其中一些,它foo接受一个int参数,而对于其他一些则没有。我正在尝试通过constexpr静态数据成员启用这些具有不同接口的策略类:

struct SimpleFoo {
    static constexpr bool paramFlag = false;
    static void foo() {
        std::cout << "In SimpleFoo" << std::endl;
    }
};

struct ParamFoo {
    static constexpr bool paramFlag = true;
    static void foo(int param) {
        std::cout << "In ParamFoo " << param << std::endl;
    }
};

template <typename FooPolicy>
struct Alg {
    void foo() {
        if (FooPolicy::paramFlag) FooPolicy::foo(5);
        else FooPolicy::foo();
    }
};

int main() {
    Alg<ParamFoo> alg;
    alg.foo();
    return 0;
}

此代码无法编译。gcc 4.8.2给出错误:

调用 'ParamFoo::foo()' 没有匹配的函数</p>

否则 FooPolicy::foo();

尽管该else子句在编译时是已知的,但仍会编译FooPolicy::paramFlag该子句true。有没有办法让它工作?

4

2 回答 2

5

有没有办法让它工作?

一种解决方案是使用标签调度:

#include <type_traits>

template <typename FooPolicy>
struct Alg {
    void foo() {
        foo(std::integral_constant<bool, FooPolicy::paramFlag>{});
    }    
private:
    void foo(std::true_type) {
        FooPolicy::foo(5);
    }
    void foo(std::false_type) {
        FooPolicy::foo();
    }
};

演示

于 2015-09-16T09:39:07.300 回答
3

您可以完全放弃该标志并使用表达式 SFINAE:

template <typename FooPolicy>
struct Alg {
    template <typename T=FooPolicy> //put FooPolicy in immediate context
    //SFINAEd out if that call is not valid
    auto foo() -> decltype(T::foo(),void()) {
        FooPolicy::foo();
    }

    template <typename T=FooPolicy>
    auto foo() -> decltype(T::foo(0),void()) {
        FooPolicy::foo(6);
    }
};
于 2015-09-16T09:42:13.900 回答