Я пытаюсь использовать std::enable_if
и SFINAE для исключения реализации метода шаблона класса, основанного исключительно на параметрах шаблона класса. Пример:
#include <type_traits>
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
template<class InnerT, class ... Args>
typename std::enable_if<!std::is_same<T1, T2>::value, void>::type
bar(InnerT param) {};
};
int main() {
Foo<int, int> f;
}
Здесь bar()
должен вести себя по-разному в зависимости от того, являются ли T1
и T2
одинаковыми или нет. Однако этот код не компилируется. Ни GCC, ни clang не говорят мне ничего полезного. Я подозреваю, что проблема заключается в том, что условие std::enable_if
не зависит от параметров bar()
, то есть не от его непосредственного контекста, как указано в пункте 17.8.2, пункт 8 стандарта.
Это предположение подтверждается тем фактом, что этот код компилируется отлично:
#include <type_traits>
class DummyClass {};
template<class T1, class T2>
class Foo {
template<class InnerT, class ... Args>
typename std::enable_if<std::is_same<T1, T2>::value ||
std::is_same<InnerT, DummyClass>::value, void>::type
bar(InnerT param) {};
template<class InnerT, class ... Args>
typename std::enable_if<!std::is_same<T1, T2>::value ||
std::is_same<InnerT, DummyClass>::value, void>::type
bar(InnerT param) {};
};
int main() {
Foo<int, int> f;
}
Теперь выражение внутри std::enable_if
зависит от "непосредственного контекста", а именно от InnerT
, хотя эта часть выражения всегда оценивается как false
.
Похоже, я могу использовать это в качестве обходного пути, но это кажется очень хакированным и уродливым. Как вы решаете эту проблему "правильно"? Я думал, что нужно добавить дополнительный параметр шаблона (назовем его DummyType
) в bar()
, который по умолчанию имеет значение, например, DummyType = T1
, а затем проверить std::is_same<DummyType, T2>
, но тот факт, что bar()
принимает пакет параметров делает это невозможным (или делает это??)