In the language reference of std::enable_if
at cppreference the following note is included
Notes
A common mistake is to declare two function templates that differ only in their default template arguments. This is illegal because default template arguments are not part of function template's signature, and declaring two different function templates with the same signature is illegal.
In the template functions in example below, it seems to me that this situation occurs. I.e., the two template functions onlyForDerivedObjects(...)
seem (to me) to differ only by their default template arguments. I realize I am missing something here, and hopefully someone can explain this to me, or point me in the direction to where I might find an epiphany for myself.
- Question: W.r.t. the quote above, why do the example below compile and run fine: do I misclassify the
typename std::enable_if ...
part in the template functions below when I consider it to yield a situation with two template functions which differ only in their default template argument?
Example
Base and derived classes:
class BaseA
{
public:
int getInt() const { return 21; };
};
class DerivedA : public BaseA {};
class BaseB
{
public:
int getAnotherInt() const { return 33; };
};
class DerivedB : public BaseB {};
with the following template functions
/* 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();
}
compiles and runs fine (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;
}