标准关于char数组作为模板参数的说法是什么? [英] What does the standard say about char arrays as template arguments?

查看:261
本文介绍了标准关于char数组作为模板参数的说法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在研究过程中找到这个问题的答案我发现(我以前不知道)gcc和clang如果声明为static,则允许将char数组用作模板参数.例如.这段代码使用gcc和clang编译:

During my research for an answer for this question I found (I did not know that before) that gcc and clang allow char arrays to be template arguments if they are declared static. E.g. this code compiles with gcc and clang:

#include <type_traits>

template <int N, const char (&string)[N]>
auto foo()
{
    if constexpr (string[0] == 'i')
        return 0;
    else
        return 3.14f;
}

void bar()
{
    static constexpr char string1[] = "int";
    static constexpr char string2[] = "float";

    auto i = foo<sizeof(string1), string1>();
    auto f = foo<sizeof(string2), string2>();

    static_assert(std::is_same_v<decltype(i), int>);
    static_assert(std::is_same_v<decltype(f), float>);
}

MSVC也允许这样做.但是,要使其与MSVC一起使用,我必须在全局命名空间中声明两个字符串.然后效果也一样.

MSVC also allows that. However, to make it work with MSVC, I have to declare the two strings in the global namespace. Then it works just as well.

所以我的问题是:标准对此有何表述?哪个编译器(如果有)是正确的?

So my question is: What does the standard say about this? Which compiler (if any) is right?

此问题已在VS 2019版本16.4(msvc v19.24)中得到修复: https://developercommunity.visualstudio.com/content/problem/341639/very-fragile-ice.html

This issue has been fixed in VS 2019 version 16.4 (msvc v19.24): https://developercommunity.visualstudio.com/content/problem/341639/very-fragile-ice.html

推荐答案

这是从C ++ 14到C ++ 17的更改,看起来MSVS尚未赶上.以前在 [temp.arg.nontype] 中是非类型参数必须是

This is a change from C++14 to C++17 that looks like MSVS hasn't caught up with. Previously in [temp.arg.nontype] a non type argument had to be

非类型,非模板模板参数的模板参数应为以下之一:

A template-argument for a non-type, non-template template-parameter shall be one of:

  • 对于整数或枚举类型的非类型模板参数,为模板参数类型的转换后的常量表达式([expr.const]);或

  • for a non-type template-parameter of integral or enumeration type, a converted constant expression ([expr.const]) of the type of the template-parameter; or

非类型模板参数的名称;或

the name of a non-type template-parameter; or

一个常量表达式([expr.const]),用于指定具有静态存储持续时间和外部或内部链接的完整对象的地址,或者具有外部或内部链接的函数,包括函数模板和函数模板ID,但不包括非静态类成员,它们表示为(忽略括号)为& id-expression,其中id-expression是对象或函数的名称,但&如果名称是指函数或数组,则可以省略;如果相应的模板参数是引用,则可以省略;或

a constant expression ([expr.const]) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or

一个常量表达式,其结果为空指针值([conv.ptr]);或

a constant expression that evaluates to a null pointer value ([conv.ptr]); or

一个常量表达式,其结果为空成员指针值([conv.mem]);或

a constant expression that evaluates to a null member pointer value ([conv.mem]); or

指向成员的指针,如[expr.unary.op]中所述;或

a pointer to member expressed as described in [expr.unary.op]; or

类型为std::nullptr_t的常量表达式.

强调我的

并且由于项目符号3,您不能使用块范围变量,因为每个 [basic.link]/10

and because of bullet 3 you could not use a block scope variable as block scope variables have no linkage per [basic.link]/10

这些规则未涵盖的名称没有链接.此外,除非另有说明,否则在块范围内声明的名称没有链接.

Names not covered by these rules have no linkage. Moreover, except as noted, a name declared at block scope has no linkage.

在C ++ 17中,此更改. [temp.arg.nontype] 现在有

In C++17 this changes. [temp.arg.nontype] now has

非类型模板参数的模板参数应为模板参数类型的转换常量表达式.对于引用或指针类型的非类型模板参数,常量表达式的值不得引用(或对于指针类型,不得为其地址):

A template-argument for a non-type template-parameter shall be a converted constant expression of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • 子对象

  • a subobject,

一个临时对象

字符串文字,

Typeid表达式的结果,或

the result of a typeid expression, or

预定义的 func__变量.

a predefined ­­func_­_­ variable.

现在,您可以使用块范围静态变量

This now allows you to use a block scope static variable

这篇关于标准关于char数组作为模板参数的说法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆