gpt4 book ai didi

c++ - `constexpr`、 `static_assert` 和 `if constexpr(...)` 变量之间的模板中 `constexpr` lambda 的评估不一致

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:46:56 27 4
gpt4 key购买 nike

(使用 g++ 7.0 主干。)

给定以下“类型到值包装”实用程序...

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{};

...我创建了以下函数来检查表达式的有效性:

template <typename TF>
constexpr auto is_valid(TF)
{
return [](auto... ts) constexpr
{
return std::is_callable<TF(typename decltype(ts)::type...)>{};
};
}

is_valid 函数可以如下使用:

// Evaluates to `true` if `some_A.hello()` is a valid expression.
constexpr auto can_add_int_and_float =
is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
(type_c<A>);

// Evaluates to `true` if `some_int + some_float` is a valid expression.
constexpr auto can_add_int_and_float =
is_valid([](auto _0, auto _1) constexpr -> decltype(_0 + _1){})
(type_c<int>, type_c<float>);

也可以在static_assert...中使用

static_assert(is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
(type_c<A>));

...在 if constexpr 中:

if constexpr(
is_valid([](auto _0) constexpr -> decltype(_0.hello()){})
(type_c<A>)) { /* ... */ }

但是,当在模板函数中使用 is_valid(将模板参数作为 type_c 值传递),会发生一些奇怪的事情: p>

  • static_assert(is_valid(/*...*/)) 正常工作。

  • constexpr auto x = is_valid(/*...*/) 正常工作。

  • if constexpr(is_valid(/*...*/) 编译失败

// 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>)) { }

为什么这仅针对 if constexpr(is_valid(/*...*/)) 情况编译失败?这与 static_assert 不一致constexpr auto x =/*...*/

这是 g++ 实现 if constexpr 的缺陷吗?

Full example on wandbox .

最佳答案

不一致的行为被报告为 bug #78131 .

关于c++ - `constexpr`、 `static_assert` 和 `if constexpr(...)` 变量之间的模板中 `constexpr` lambda 的评估不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40283001/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com