在不带constexpr的模板非类型参数中进行类型转换 [英] Type conversion at template non-type argument without constexpr

查看:391
本文介绍了在不带constexpr的模板非类型参数中进行类型转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

  struct A {
constexpr operator int(){return 42; }
};

template< int>
void foo(){}

void bar(A a){
foo< a>();
}

int main(){
foo< A {}>();

const int i = 42;
foo< i>(); //(1)

A a {};

static_assert(i == a,);
bar(a);
foo< a>(); // error here
}

Clang 3.7 with c ++ 14接受这个,而gcc 5.2.0与c ++ 14不会,产生以下消息:


  / tmp / gcc-explorer-compiler1151027-68-1f801jf / example.cpp:在函数'int main()'中:
26:错误:'a'的值在常量表达式中不可用
foo< a>();
^
23:注意:'a'未声明为'constexpr'
A a {};
^
编译失败


gcc修复了gcc编译错误,但没有 constexpr ccc建议的code> a code>,编译器是正确的吗?



对我来说,似乎 a 在常量表达式,如 static_assert ceritifies。此外, i 可以以相同的方式使用(标记为(1)), code> bar()编译,也让我认为gcc是错误的。



UPD 报告了针对gcc的错误: https://gcc.gnu.org/bugzilla/show_bug .cgi?id = 68588 //eel.is/c++draft/expr.const#4rel =nofollow> [expr.const] /(4.1),而且我没有看到一个适用的项目符号, a href =http://eel.is/c++draft/expr.const#2 =nofollow> [expr.const] / 2 ,这将阻止您的表达式成为常量表达式。事实上,要求是如此宽松,声明 a

  A一个; 

仍然给出一个格式良好的程序,即使 a 没有 constexpr 默认构造函数等,因为转换运算符 constexpr 并且没有成员被求值。



正如你所看到的,GCC是矛盾的,因为它允许 static_assert中的 a 条件,而不是模板参数。


Consider the following code:

struct A {
    constexpr operator int() { return 42; }
};

template <int>
void foo() {}

void bar(A a) {
    foo<a>();
}

int main() {
    foo<A{}>();

    const int i = 42;
    foo<i>();  // (1)

    A a{};

    static_assert(i == a, "");
    bar(a);
    foo<a>();  // error here
}

Clang 3.7 with c++14 accepts this, while gcc 5.2.0 with c++14 does not, producing the following message:

/tmp/gcc-explorer-compiler1151027-68-1f801jf/example.cpp: In function 'int main()':
26 : error: the value of 'a' is not usable in a constant expression
foo<a>();
^
23 : note: 'a' was not declared 'constexpr'
A a{};
^
Compilation failed

Changing a to be constexpr as suggested by gcc fixes the gcc compilation error, but without constexpr, which compiler is right?

For me, it seems that a should be "usable in constant expression", as static_assert ceritifies. Moreover, the fact that i can be used the same way (marked (1)), and the fact that bar() compiles, also makes me think that gcc is wrong.

UPD: reported a bug against gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68588

解决方案

The user-defined conversion is allowed by [expr.const]/(4.1), and I don't see a single applicable bullet point in [expr.const]/2 that would prevent your expression from being a constant one. In fact, the requirements are so loose that declaring a as

A a;

is still giving a well-formed program, even if a didn't have a constexpr default constructor etc., since the conversion operator is constexpr and no members are evaluated.

As you saw yourself, GCC is contradictory in that it allows a in the static_assert condition but not a template-argument.

这篇关于在不带constexpr的模板非类型参数中进行类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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