使用 std::enable_if 作为 templ 时的默认模板参数.参数:为什么可以使用两个仅在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?

本文关键字:参数 if enable 可以使 两个 templ 作为 std 使用 默认 为什么      更新时间:2023-10-16

在cpp首选项的std::enable_if语言参考中,包括以下注释

笔记

一个常见的错误是声明两个不同的函数模板 仅在其默认模板参数中。这是非法的,因为 默认模板参数不是函数模板的一部分 签名,并使用 相同的签名是非法的。

在下面的示例中的模板函数中,在我看来,这种情况发生了。 也就是说,这两个模板函数似乎(对我来说)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;
}

笔记

一个常见的错误是声明两个函数模板,它们仅在默认模板参数上有所不同。这是非法的,因为默认模板参数不是函数模板签名的一部分,并且声明具有相同签名的两个不同的函数模板是非法的。

您的函数不仅在默认模板参数上有所不同,而且在模板参数上也不同,因此具有不同的签名。

在这两种情况下,默认模板参数都是 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();