使用 std::enable_if 作为模板时的默认模板参数。 param.: 为什么只有 enable_if 参数不同的两个模板函数可以?

Default template argument when using std::enable_if as templ. param.: why OK with two template functions that differ only in the enable_if parameter?

language reference of std::enable_if at cppreference 中包含以下注释

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.

在下面例子中的模板函数中,我觉得是出现了这种情况。即,两个模板函数 onlyForDerivedObjects(...) 似乎(对我而言)仅在它们的默认模板参数上有所不同。我意识到我在这里遗漏了一些东西,希望有人可以向我解释这一点,或者为我指明方向,让我可以为自己找到顿悟。

例子

基础和派生类:

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;
}

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.

您的函数不仅在默认模板参数方面有所不同,它们在模板参数方面也有所不同,因此具有不同的签名。

在这两种情况下,默认模板参数 都是nullptr,但是第二个模板参数 在每种情况下都不同。

常见的错误是:

template <typename T, typename = std::enable_if_t<cond>>
void foo()

template <typename T, typename = std::enable_if_t<!cond>>
void foo()

两者都声明

template <typename, typename>
void foo();