代码之家  ›  专栏  ›  技术社区  ›  ThaPear

将类成员声明为模板参数

  •  0
  • ThaPear  · 技术社区  · 11 年前

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

    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:“void B::Test(void)”:无法转换“this”指针 从“C”到“B&”原因:无法从“C”转换为“B”转换 需要第二个用户定义的转换运算符或构造函数

    但是,如果我使用以下代码,它确实有效:

    decltype(c.a) d;
    b.Test<decltype(d)>();
    

    如果我直接使用类成员,为什么它不起作用? 我正在使用Visual Studio 2012。

    2 回复  |  直到 11 年前
        1
  •  1
  •   Community Mohan Dere    9 年前

    7.1.6.2(4)

    对于表达式 e ,由表示的类型 decltype(e) 定义如下:

    • 如果 e 是不带括号的 id表达式 或非括号类成员访问 (5.2.5), 下降型(e) 由命名的实体的类型 e .
    • 如果没有此类实体,或如果 e 命名一组重载函数,程序格式不正确;
    • 否则,如果 e 是x值, 下降型(e) T&& 哪里 T 是的类型 e ;
    • 否则,如果 e 是左值, 下降型(e) T& 哪里 T 是的类型 e ;
    • 否则 下降型(e) 是的类型 e .

    VS2012似乎忘记了(或从未被告知)我大胆的部分,例如 e 是不带括号的类成员访问。因此,它可能会在什么时候回归规则 e 是左值,因此对于VS2012 decltype(c.a) 表示 int& (提及 int ).

    示例还包含一个以开头的标识符 _ 和一个大写字母( _T )这是未定义的行为。看见 What are the rules about using an underscore in a C++ identifier?

        2
  •  1
  •   vsoftco    11 年前

    我认为在类中定义专门化是不合法的,它必须在命名空间级别(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)>();
    }