我有一个程序如下。有一个基本模板struct X
,以及SFINAE的部分专业化。
template <typename T, typename U = void>
struct X{
X() {
std::cout << "in 1" << std::endl;
};
};
template <typename T>
struct X< T, std::enable_if_t<std::is_integral_v<T>> > {
X() {
std::cout << "in 2" << std::endl;
};
};
int main() {
X<int> x;
}
在2运行程序时,将打印。
>
为什么基本模板的默认类型参数必须与局部特化定义的类型相同,才能调用局部特化并打印2
中的。为什么更改为
std::enable_if_t
1) [...] 什么使std::启用\u如果\u t
那么您知道吗,如果两个模板匹配,则选择更专业的模板。
好第二个更专业化,因为如果X
与专业化匹配(因此如果X
是一个整数类型),那么它也与通用版本匹配。
但是存在一些类型(例如:std::string
,void
),它们与泛型版本匹配,而与专门化不匹配。
因此,专用化比通用版本更专用,因此在两个模板匹配时,首选专用化。
为什么基本模板的默认类型参数必须与部分专业化定义的类型相同,才能调用部分专业化并在2中打印。为什么更改为std::启用\u if\u t,bool
您必须了解默认类型值的技巧是如何工作的。
你有一个通用的版本
template <typename T, typename U = void>
struct X;
所以写X
专业化是
template <typename T>
struct X< T, std::enable_if_t<std::is_integral_v<T>>>;
问题:
X
回答:是的,因为
int
是整数,所以std::enable\u if\t
假设现在泛型专门化成为
template <typename T>
struct X< T, std::enable_if_t<std::is_integral_v<T>, bool>>
我们有
X
问题:
X
回答:没有,因为
std::启用
因此,通用版本是唯一匹配并被选中的版本。
您的问题的答案在于模板部分订购。这是编译器用来确定哪个模板最适合的机制(无论是函数模板重载,还是在您的情况下,类模板专门化)。
简而言之,您的通用模板实现有两个参数T
和U
,而您的SFINAE专门化只有T
参数,而第二个参数是从T
推导出来的。因此,它比一般情况更专业,最后,当您引用X时
现在问题2。假设我们将
enable_if
参数替换为bool
而不是val
。现在我们的专业化将是X
如果允许我执行以下操作: 为什么我主要不被允许做以下事情? 但我必须具体说明以下几点: C11引入了默认的模板参数,现在我完全无法理解它们。
问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7
函数模板、成员函数模板、或类模板的成员函数或静态数据成员的专门化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于在翻译单元内具有实例化点的任何这样的专门化,翻译单元的末尾也被认为是实例化点。类模板的专门化在翻译单元中最多有一个实例化点。任何模板的专门化都可能在多个翻译单元中具有实例化点。如果两个不同的实例化点根据一个定义规则赋予一个模板专门化不同的含义,则程序是格式不良的,不需要诊
是否允许在友元声明中为模板参数提供默认值? Visual Studio 2015似乎允许这样做。gcc拒绝了。我在cppreference页面上找不到任何内容。
标准中似乎没有规则提到模板参数需要默认参数的情况。 在dcl中。fct。默认值#1 如果在参数声明中指定了初始化子句,则将此初始化子句用作默认参数。缺省参数将用于缺少尾随参数的调用。 在本节中,规则明确描述了何时为函数调用提供默认参数。但是,我在标准中没有找到与上面描述何时提供默认参数作为模板参数的语句类似的引用。 例如
函数模板专门化的主模板通常很直观,然而,我正在寻找形式规则来理解更令人惊讶的情况。例如: 理论上,(3)也可以是(1)的特化,但实验表明不是。