【问题标题】:Decltype on class member as template argument类成员上的 Decltype 作为模板参数
【发布时间】:2014-10-04 14:24:36
【问题描述】:

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

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。

【问题讨论】:

  • 我不知道这是否是问题所在,但 Visual Studio 对 C++11 的支持不完整。 VS2013更好。试试 oneide.com 上的代码
  • VS2012 中的 decltype 非常糟糕。但是,这已在 VS2013 中修复。
  • 这确实是Visual Studio 2012的问题,Visual Studio 2013编译它没有问题。模板专业化只是为了表明它适用于第二个版本。它不是最初错误代码的一部分。

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


【解决方案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)>();
}

【讨论】:

  • 这段代码在 VS2013 中编译得很好,但是你已经根据 §14.7.3/2 Explicit specialization [temp.expl.spec] 弄清楚了,这不是符合标准的行为,而是 VS 扩展。
【解决方案2】:

7.1.6.2(4)

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

  • 如果e 是一个未加括号的id-expression 或一个未加括号的类成员访问 (5.2.5),decltype(e) 是由 命名的实体的类型e。
  • 如果不存在这样的实体,或者如果e 命名了一组重载函数,则程序是非良构的;
  • 否则,如果e是一个xvalue,decltype(e)就是T&amp;&amp;,其中T是e的类型;
  • 否则,如果e是左值,decltype(e)就是T&amp;,其中T是e的类型;
  • 否则,decltype(e) 是 e 的类型。

VS2012 似乎忘记了(或从未被告知)我加粗的部分,e 是一个未加括号的类成员访问。因此它可能会退回到e 是左值时的规则,因此对于 VS2012,decltype(c.a) 表示int&amp;(对int 的引用)。

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

【讨论】:

  • 感谢您的明确答复。但是,我很困惑:标识符 _T 有什么问题?你能详细说明一下吗?例如,当我查看 时,我会看到像 _Ty 这样的东西。事实上,那里使用的大多数类型都以_ 和大写字母开头。
  • @ThaPear 这正是原因。 &lt;vector&gt; 是标准库的一部分,这是唯一允许的地方。见What are the rules about using an underscore in a C++ identifier?
猜你喜欢
  • 2023-04-02
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多