我试图将类成员的类型作为模板参数传递。为此,我使用以下代码:
class C
{
public:
int a;
};
class B
{
public:
template<typename _T> void Test() {}
// Specialize for int for Test testing purposes.
template<> void Test<int>() { printf("Success!\n"); }
};
//Later:
B b;
C c;
b.Test<decltype(c.a)>();
这给了我以下错误:
错误C2662:&#39;无效B ::测试(无效)&#39; :不能转换这个&#39;指针 来自&#39; C&#39;到&#39; B&amp;&#39;原因:无法转换为&#39; C&#39;到&#39; B&#39;转变 需要第二个用户定义转换运算符或构造函数
但是,如果我使用以下代码,它确实有效:
decltype(c.a) d;
b.Test<decltype(d)>();
如果我直接使用类成员,为什么它不起作用? 我使用的是Visual Studio 2012。
答案 0 :(得分:1)
我认为在类中定义一个特殊化是合法的,它必须在命名空间级别(g ++不编译你的代码,error: explicit specialization in non-namespace scope 'class B'
)。尝试在课堂外定义模板,
template<> void B::Test<int>() { printf("Success!\n"); }
这段代码对我来说非常好(在g ++上),如果它不适合你,它可能是一个VS问题。
#include <iostream>
using namespace std;
class C
{
public:
int a;
};
class B
{
public:
template<typename _T>
void Test() {}
// Specialize for int for Test testing purposes.
};
template<> void B::Test<int>() { cout << "Success!\n"; }
int main()
{
B b;
C c;
b.Test<decltype(c.a)>();
}
答案 1 :(得分:1)
7.1.6.2(4)
对于表达式
e
,decltype(e)
表示的类型定义如下:
- 如果
命名的实体e
是未加密码的 id-expression 或未加隐身的类成员访问(5.2.5),则decltype(e)
是由e
。- 如果没有这样的实体,或者如果
e
命名了一组重载函数,那么该程序就会格式不正确;- 否则,如果
e
是xvalue,则decltype(e)
为T&&
,T
的类型为e
;- 否则,如果
e
是左值,则decltype(e)
为T&
,T
的类型为e
;- 否则,
的类型decltype(e)
是e
。
VS2012似乎忘记了(或者从未被告知过)我加粗的部分,e
是一个无表情的类成员访问的情况。因此,当e
为左值时,可能会回退到规则,因此对于VS2012,decltype(c.a)
表示int&
(对int
的引用)。
您的示例还包含以_
开头的标识符和大写字母(_T
),这是未定义的行为。见What are the rules about using an underscore in a C++ identifier?