1

我正在尝试过滤传递给重载函数模板的类型的方法。我正在使用 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;
}
4

2 回答 2

2

回答 1/2 关于 SFINAE 不起作用的原因:

SFINAE模板参数推导在这种情况下不能很好地配合使用。

或者,只要您知道事情发生的正确顺序,他们就会这样做。

必须保证推导能够被视为在这种情况下调用的可能函数。

这是一种以技术含量较低的方式看待这个问题的方法:

  1. 编译器搜索与您尝试调用的内容相匹配的可能函数签名。[参见重载解决方案]

  2. 如果它找到一个模板参数,它会查看它是否对扣除有效。

这就是您遇到问题的原因。这两个事件发生的顺序是 SFINAE 工作的原因Blorg1Blorg2TFoo1不是Blorg3or TFoo2

WithBlorg3并且TFoo2编译器无法插入您传递给模板类型的参数,因为它会创建无法解决的循环依赖关系。

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. 但是,T直到 SFINAE 得到解决才知道。

为什么TFoo2不起作用也是如此。

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

是的,您可以将模板参数传递给构造函数,但前提是您必须通过演绎来完成,例如使用TFoo1.

您不能将模板参数显式传递给构造函数。

于 2015-01-19T21:46:23.877 回答
1

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

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

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

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

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

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

于 2015-01-19T21:13:38.880 回答