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