繁体   English   中英

模板参数推导和SFINAE - 使用std :: enable_if

[英]Template argument deduction and SFINAE - using std::enable_if

我正在尝试过滤传递给重载函数模板的类型的方法。 我正在使用Visual Studio 2013。

三部分问题:

  1. 为什么我的编译器不能推断出Blorg3
  2. TFoo2(argc)生成与#1相同的编译器错误的原因是什么?
  3. 有没有办法将模板参数传递给构造函数?

以下是示例代码:

#include <type_traits>

#define IFPTR(T,R) typename std::enable_if<std::is_pointer<T>::value, R>::type
#define IFINT(T,R) typename std::enable_if<std::is_integral<T>::value, R>::type

template <class T, IFINT(T, T)* = nullptr> int Blorg1(T n)  { return n + 1; }
template <class T, IFPTR(T, T)* = nullptr> int Blorg1(T n)  { return *n + 1; }
template <class T> IFINT(T, int) Blorg2(T n)                { return n + 1; }
template <class T> IFPTR(T, int) Blorg2(T n)                { return *n + 1; }
template <class T> int Blorg3(IFINT(T, T) n)                { return n + 1; }
template <class T> int Blorg3(IFPTR(T, T) n)                { return *n + 1; }

struct TFoo1 {
    template <class T, IFINT(T, T)* _ = nullptr> TFoo1(T n) { }
};
struct TFoo2 {
    template <class T> TFoo2(IFINT(T, T) n) { }
};

int main(int argc, char* argv[])
{
    Blorg1(argc); // intellisense not happy
    Blorg2(argc);
    Blorg3<int>(argc);  // why cant deduce?
    Blorg1(*argv); // intellisense not happy
    Blorg2(*argv); 
    Blorg3<char*>(*argv); // why cant deduce?
    (void)TFoo1(argc); // intellisense not happy
    (void)TFoo2(argc); // intellisense not happy and !!wont compile!!
    return 0;
}

答案为1/2关于SFINAE不工作的原因:

在此上下文中, SFINAE模板参数推导不能很好地协同工作。

或者,只要你知道发生了正确的秩序,他们就会这么做。

必须保证推论被认为是在这种情况下要调用的可能函数。

这是一种以较少技术方式来看待这种情况的方法:

  1. 编译器会搜索与您尝试调用的函数签名相匹配的函数签名。 [见重载决议]

  2. 如果找到模板参数,它会查看它是否对推导有效。

这就是你遇到问题的原因。 这两个事件发生的顺序是为什么SFINAE对Blorg1Blorg2TFoo1起作用的Blorg1 ,而不是Blorg3TFoo2

使用Blorg3TFoo2 ,编译器无法将您传递给模板类型的参数插入,因为它会创建无法解析的循环依赖项。

template <class T> int Blorg3(IFINT(T, T) n)                { return n + 1; }
template <class T> int Blorg3(IFPTR(T, T) n)                { return *n + 1; }
Blorg3<char*>(*argv); // why cant deduce?

要解决Blorg3的SFINAE,需要知道T 但是,直到SFINAE解决后才知道T

这同样适用于TFoo2不起作用的原因。

第3部分 - 关于模板和构造函数

是的,您可以将模板参数传递给构造函数,但TFoo1是您通过演绎(例如TFoo1所做的操作)来TFoo1

您无法将模板参数显式传递给构造函数。

为什么我的编译器不能推断出Blorg3?

std::enable_if<std::is_pointer<T>::value, R>::type::type是指依赖于模板参数TR的嵌套名称。 这是一个非推导的上下文(§14.8.2.5/ 5),因此编译器不会推导出模板参数。

这就是TFoo2(argc)生成编译器错误的原因吗?

是的,构造函数模板必须能够推导出它的模板参数,在这种情况下它不能。

是否有语法为构造函数提供模板参数?

不,正如我已经提到的,你不能明确地这样做,必须推断它们,或者模板参数必须有默认参数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM