将类成员上的Decltype作为模板参数

时间:2014-08-11 17:09:14

标签: c++ templates visual-studio-2012 member decltype

我试图将类成员的类型作为模板参数传递。为此,我使用以下代码:

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。

2 个答案:

答案 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)

  

对于表达式edecltype(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?