Я пытаюсь использовать 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() принимает пакет параметров делает это невозможным (или делает это??)