В ссылка на язык std::enable_if
на cppreference включена следующая заметка
Примечания
Общей ошибкой является объявление двух шаблонов функций, которые различаются только в аргументах шаблона по умолчанию. Это незаконно, потому что аргументы шаблона по умолчанию не являются частью шаблона функции. подпись и объявление двух разных шаблонов функций с помощью та же подпись незаконна.
В функциях шаблона в примере ниже мне кажется, что эта ситуация происходит. I.e, две функции шаблона onlyForDerivedObjects(...)
кажутся (мне) различающимися только их аргументами шаблона по умолчанию. Я понимаю, что здесь что-то не хватает, и, надеюсь, кто-то может объяснить это мне или указать мне в сторону, где я могу найти прозрение для себя.
- Вопрос: W.r.t. цитата выше, почему приведенный ниже пример компилируется и выполняется нормально: не классифицирую ли я часть
typename std::enable_if ...
в функциях шаблона ниже, когда я считаю, что это создает ситуацию с двумя функциями шаблона, которые отличаются только аргументом шаблона по умолчанию?
Пример
Базовые и производные классы:
class BaseA
{
public:
int getInt() const { return 21; };
};
class DerivedA : public BaseA {};
class BaseB
{
public:
int getAnotherInt() const { return 33; };
};
class DerivedB : public BaseB {};
со следующими функциями шаблона
/* template functions that, seemingly, only differ in their
default template arguments? */
template< class T,
typename std::enable_if<std::is_base_of<BaseA, T>::value>::type* = nullptr >
int onlyForDerivedObjects(const T& obj)
{
return 2*obj.getInt();
}
template< class T,
typename std::enable_if<std::is_base_of<BaseB, T>::value>::type* = nullptr >
int onlyForDerivedObjects(const T& obj)
{
return 3*obj.getAnotherInt();
}
компилируется и работает отлично (g++ -Wall -std=c++11 ...
, g++ 4.9.3
)
#include <iostream>
#include <type_traits>
/* ... classes and template functions as above */
/* template argument deduction seems to work fine */
int main()
{
DerivedA* objA = new DerivedA();
DerivedB* objB = new DerivedB();
std::cout << onlyForDerivedObjects(*objA) << std::endl; // 42
std::cout << onlyForDerivedObjects(*objB) << std::endl; // 99
return 0;
}