Классы политик с разными интерфейсами

Предположим, что алгоритм имеет политику 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()

еще FooPolicy::foo();

else предложение компилируется несмотря на то, что во время компиляции известно, что FooPolicy::paramFlag является true, Есть ли способ заставить его работать?

2 ответа

Решение

Есть ли способ заставить его работать?

Одним из решений является использование диспетчеризации тегов:

#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();
    }
};

DEMO

Вы можете полностью отказаться от флага и использовать выражение 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);
    }
};
Другие вопросы по тегам