【问题标题】: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?使用 std::enable_if 作为模板时的默认模板参数。参数:为什么两个模板函数只在 enable_if 参数上有区别?
【发布时间】:2016-07-11 10:59:10
【问题描述】:

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

备注

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

在下面示例中的模板函数中,在我看来这种情况发生了。即,两个模板函数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;
}

【问题讨论】:

    标签: c++ templates c++11 enable-if


    【解决方案1】:

    备注

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

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

    在这两种情况下,默认模板 argumentnullptr,但第二个模板 parameter 在每种情况下都不同。

    【讨论】:

    • 你能详细说明一下,它们有什么不同吗?据我的理解:两种类型都解决为 void* 或什么都没有。对于这两种情况,默认值都是 nullptr,所以对我来说它们是完全相同的。
    • @DawidPilarski 签名包括整个enable_if 类型,而不仅仅是它在扣除后解析的内容。这些类型是不同的,因为它们依赖于不同的表达式(一种使用is_base_of&lt;BaseA, T&gt;,一种使用is_base_of&lt;BaseB, T&gt;)。
    【解决方案2】:

    常见的错误是:

    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();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-18
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      相关资源
      最近更新 更多