C++ “static_assert”、“if constexpr(…)”和“constexpr”变量之间对模板中的“constexpr”lambdas的计算不一致
(使用C++ “static_assert”、“if constexpr(…)”和“constexpr”变量之间对模板中的“constexpr”lambdas的计算不一致,c++,lambda,constexpr,c++17,constant-expression,C++,Lambda,Constexpr,C++17,Constant Expression,(使用g++7.0trunk。) 给定以下“类型到值包装”实用程序 template <typename T> struct type_wrapper { using type = T; }; // "Wraps" a type into a `constexpr` value. template <typename T> constexpr type_wrapper<T> type_c{}; 它也可以在静态断言中使用 static_assert(is_v
g++7.0
trunk。)
给定以下“类型到值包装”实用程序
template <typename T>
struct type_wrapper { using type = T; };
// "Wraps" a type into a `constexpr` value.
template <typename T>
constexpr type_wrapper<T> type_c{};
它也可以在静态断言
中使用
static_assert(is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
(type_c<A>));
但是,当在模板函数中使用
is\u valid
时(将模板参数作为type\u c
值传递),会发生一些奇怪的情况:
工作正常静态断言(是否有效(/*…*/)
工作正常constexpr auto x=有效(/*…*/)
编译失败如果constexpr(有效(/*…*/)
//按预期编译和工作。
模板
无效和0(T0,T1)
{
静态断言(
_是否有效([](自动_0,自动_1)constexpr
->decltype(0+1){})(类型c,类型c)
);
}
//按照预期进行编译和工作。
模板
无效总和(T0,T1)
{
constexpr自动计算=
_是否有效([](自动_0,自动_1)constexpr
->decltype(0+1){})(类型c,类型c);
if constexpr(can_sum){}
}
//编译时错误!
模板
无效和失效0(T0,T1)
{
如果constexpr(是有效的([](自动0,自动1)constexpr
->decltype(0+1){})(类型_c,类型_c)){}
}
错误:
In function 'void sum_fail_0(T0, T1)':
64:95: error: expression '<lambda>' is not a constant expression
if constexpr(is_valid([](auto _0, auto _1) constexpr -> decltype(_0 + _1){})(type_c<T0>, type_c<T1>)) { }
函数“无效和失败0(T0,T1)”中的
64:95:错误:表达式“”不是常量表达式
如果constexpr(是有效的([](自动0,自动1)constexpr->decltype(0+1){})(type_c,type_c)){}
如果constexpr(是否有效(/*…*/)情况下,为什么无法仅为编译?
这与静态断言和constexpr auto x=/*…*/
不一致
这是g++
实现if constexpr
的一个缺陷吗
.据我所知,lambda本身不是一个constepr
。
你能行
constexpr auto f = [](auto _0, auto _1) -> decltype(_0 + _1){};
然后
if constexpr(is_valid(f)(type_c<T0>, type_c<T1>)) { }
如果constexpr(是有效的(f)(类型c,类型c)){
不一致的行为被报告为。你重新发明了。@SamVarshavchik:不再是:)看起来肯定像个bug。即使明确地说是有效的([](自动0,自动1)constexpr->decltype(_0+_1){
不会改变结果。为什么将lambda本身放入constexpr
变量和static\u assert
中会起作用,但如果constexpr
中则不会起作用?
// Compiles and works as intended.
template <typename T0, typename T1>
void sum_ok_0(T0, T1)
{
static_assert(
is_valid([](auto _0, auto _1) constexpr
-> decltype(_0 + _1){})(type_c<T0>, type_c<T1>)
);
}
// Compiles and works as intended.
template <typename T0, typename T1>
void sum_ok_1(T0, T1)
{
constexpr auto can_sum =
is_valid([](auto _0, auto _1) constexpr
-> decltype(_0 + _1){})(type_c<T0>, type_c<T1>);
if constexpr(can_sum) { }
}
// Compile-time error!
template <typename T0, typename T1>
void sum_fail_0(T0, T1)
{
if constexpr(is_valid([](auto _0, auto _1) constexpr
-> decltype(_0 + _1){})(type_c<T0>, type_c<T1>)) { }
}
In function 'void sum_fail_0(T0, T1)':
64:95: error: expression '<lambda>' is not a constant expression
if constexpr(is_valid([](auto _0, auto _1) constexpr -> decltype(_0 + _1){})(type_c<T0>, type_c<T1>)) { }
constexpr auto f = [](auto _0, auto _1) -> decltype(_0 + _1){};
if constexpr(is_valid(f)(type_c<T0>, type_c<T1>)) { }