Я пытаюсь придумать функцию-член для класса шаблона, которая:
Не уверен, применимо ли к этому SFINAE, поскольку мне нужны обе версии, поскольку я называю их в самом классе. Обратите внимание, я ограничен C++ 11.
template < typename T_ = T, typename = std::enable_if_t <!std::is_pointer<T_>{} > >
void SomeFunction()
{
// Do nothing
}
template < typename T_ = T, typename = std::enable_if_t < std::is_pointer<T_>{} > >
void SomeFunction()
{
// Do sth
}
Компилятор жалуется, что ошибка C2535: функция-член уже определена или объявлена.
Еще один скомпилированный SFINAE, который можно сделать очень тривиальным с помощью C++ 17 if constexpr.





Проблема в том, что аргументы шаблона по умолчанию не являются частью подпись шаблона функции. Два SomeFunction считаются идентичными, что вызывает ошибку повторного объявления.
Two function templates are considered equivalent if
- they are declared in the same scope
- they have the same name
- they have identical template parameter lists
- the expressions involving template parameters in their return types and parameter lists are equivalent
Вы можете использовать их в возвращаемых типах, например (для C++ 11)
template <typename T_ = T>
typename std::enable_if<!std::is_pointer<T_>::value>::type SomeFunction()
{
// Do nothing
}
template <typename T_ = T>
typename std::enable_if<std::is_pointer<T_>::value>::type SomeFunction()
{
// Do sth
}
Или используйте их в списке параметров шаблона без типа, например (для C++ 11)
template < typename T_ = T, typename std::enable_if<!std::is_pointer<T_>::value>::type* = nullptr>
void SomeFunction()
{
// Do nothing
std::cout << "Do nothing\n";
}
template < typename T_ = T, typename std::enable_if<std::is_pointer<T_>::value>::type* = nullptr>
void SomeFunction()
{
// Do sth
std::cout << "Do sth\n";
}
Отлично! Немного более чистая версия была бы template < typename T_ = T, typename std::enable_if_t < !std::is_pointer<T_>{} >* = nullptr>
Проблема в том, что два объявления шаблона функции - это эквивалент, поэтому компилятор считает, что ваш код содержит 2 определения функций для уникальной функции.
Эквивалентность шаблонов функций описана в [temp.over.link] / 6 и [temp.over.link] / 7.
В вашем конкретном случае проблема в том, что этот эквивалентность не принимает во внимание аргумент шаблона по умолчанию.
Если вы добавите параметр шаблона по умолчанию, эти две функции не будут эквивалентны:
template < typename T_ = T
, typename = std::enable_if_t <!std::is_pointer<T_>{} > >
void SomeFunction()
{
// Do nothing
}
template < typename T_ = T
, class=void
, typename = std::enable_if_t < std::is_pointer<T_>{} > >
void SomeFunction()
{
// Do sth
}