【问题标题】:Some trouble passing a "const char" parameter in templates even in Visual C++ Compiler Nov 2013 CTP即使在 Visual C++ 编译器 2013 年 11 月 CTP 中,在模板中传递“const char”参数也会遇到一些问题
【发布时间】:2014-01-07 09:29:33
【问题描述】:

大家好,新年快乐,

即使在 Visual C++ 的最新版本 Compiler 2013 年 11 月 CTP 中,我在模板中传递“const char”参数时也遇到了一些麻烦!这是在最新的 Visual C++ 编译器中不起作用的简单代码,但可以使用带有选项“std=c++x0”的“g++”,

#include <stdlib.h>


template<char _parameterChar>
class A
{
    char varChar;
public:
    A(){ varChar = _parameterChar; }
    ~A(){}
};


int main(int argc, char* argv[])
{
    const char a_1 = 'a';
    const char a_2 = "abcdef"[0]; // This instruction gets a constant 'a'.


    A<'a'> first_A; // compile ok!
    A<a_1> second_A; // compile ok!
    A<a_2> third_A; // --->  This not compiles!! Why not ?!?!?!

    return 0;
}

Visual C++ 编译器给出该错误,

error C2971: 'A' : template parameter '_parameterChar' : 'a_2' : a local variable cannot be used as a non-type argument

我认为这是对编译器的限制,因为“abcdef”[0],你可以在编译时得到 const char 'a',不是吗?

【问题讨论】:

  • @hetepeperfan:据我所知,它是一个常量表达式,因此可以用作模板参数。你认为究竟是什么使它无法成为一个常量表达式?
  • 这段代码使用g++ (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 编译得很好。问题可能是您使用的编译器在编译时没有推断出"abcdef"[0] 的值?
  • 对于它的价值,Clang 也拒绝了这一点。但我很难看出是什么使 "abcdef"[0] 无法成为常量表达式,所以我不能说哪个编译器是正确的。
  • @MikeSeymour 我认为它在 C++11 中可能是合法的,但在 C++11 之前的版本中肯定不是。 (如果 g++ 支持它作为扩展,我也不会感到惊讶,即使在 C++11 之前也是如此。)
  • 奇怪的是const char a_2 = "abcde"[0];是合法的,但是在模板参数中被拒绝了。

标签: c++ templates parameter-passing


【解决方案1】:

简单的答案是标准说"abcdef"[0] 不是一个常量表达式。从逻辑上讲,编译器可能会解决它,但标准并未将其列在允许的操作中。表达式的评估涉及左值到右值的转换,并且只允许非常有限数量的左值到右值的转换。 (实际上,在 C++11 中它可能是合法的。但如果是这种情况,那将是一个新功能,并且可能不会由您的编译器实现。)

【讨论】:

  • 如我所说,我使用最新的编译器 Nov 2013 CTP。我不知道是否必须配置特定的构建选项。尽管 C++ 标准这么说,但我认为这对我来说是正确的 const value rvalue。
  • @JordiEspada 它绝对不在旧的 C++ 中。对人类读者来说,它可能看起来是 const,但考虑到编译器的工作方式,它对编译器来说并不明显。
  • @JordiEspada 关于编译器,Visual C++ 尚不支持许多 C++11 功能。 (大多数编译器也是如此。)这看起来将被msdn.microsoft.com/en-us/library/hh567368.aspx 表中的“constexpr”条目所涵盖;换句话说,即使在最新版本的 Visual Studios 中,它也受支持。
【解决方案2】:

James Kanze 说“abcdef”[0] 不是一个常量表达式,但我认为它来自标准。

标准 5.19.3

整数常量表达式是整数或 无作用域枚举类型,隐式转换为纯右值,其中 转换后的表达式是核心常量表达式。

标准 5.19.2

左值到右值的转换(不是核心常量表达式),除非它应用于:

整数或枚举类型的非易失性左值,它指代 具有先前初始化的非易失性 const 对象, 用常量表达式 [ 注意:字符串字面量初始化 (2.14.5) 对应于此类对象的数组。 ——尾注],

【讨论】:

  • 那你说的是不是字符串文字是通过常量字符初始化的,不是吗?
  • 不完全是,我所说的字符串字面量是一个 const 对象的数组,因此这个数组中的每个元素都应该是一个 const 对象,即“abcdef”[0] 应该是一个 const 对象。
  • @user534498 我没说不是;我说我不确定(在 C++11 中——在 C++11 之前的版本中,显然不是)。我目前倾向于说是,但我不是 100% 确定。但即使它是在 C++11 中,与早期版本相比,这也是一个重大变化,而且编译器很可能还不支持它。 (我可以访问的所有编译器都没有完全支持 C++11。虽然它们都支持某些特性,但它们并不总是你最想要的特性。)
【解决方案3】:

目前,此代码可在 Visual Studio 2017 (Windows) 上按预期编译和工作。不需要做具体的配置设置,默认控制台应用程序就够了。不幸的是,我无法在以前版本的 VS 上检查它。

【讨论】:

  • 你是对的 Pavel K。我不得不等待更新版本的 MSVC++ :)
猜你喜欢
  • 2016-01-09
  • 2013-01-11
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 2014-02-11
  • 2013-01-03
  • 1970-01-01
  • 2011-04-15
相关资源
最近更新 更多