gpt4 book ai didi

c++ - 带 std::get 的 SFINAE constexpr

转载 作者:可可西里 更新时间:2023-11-01 17:57:26 25 4
gpt4 key购买 nike

这是 Detecting constexpr with SFINAE 的后续问题.

我想检测元组的元素(或任何可以与 std::get 一起使用的元素)是否为 constexpr。所以我写了以下类似于 Xeo 给出的助手:

template<size_t> struct sfinae_true : std::true_type{};

template<size_t N, class T>
auto check(const T& arg) -> sfinae_true<(std::get<N>(arg),N)>;

template<size_t N, class>
std::false_type check(...);

现在我的测试驱动程序代码:

int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
typedef decltype(check<0,decltype(arg)>(arg)) is_cexpr;
std::cout << "is constexpr? " << is_cexpr::value << '\n';
}

但是,这总是打印出 false为了我!为了检查是否由于某种原因并不总是调用错误的重载,我注释掉了错误的重载并得到了编译器错误:

note: candidate template ignored: substitution failure [with N = 0, T = const std ::tuple]: non-type template argument is not a constant expression
auto check(const T& arg) -> sfinae_true<(std::get(arg),0)>;

不过,我知道我可以调用 std::get<N>(arg)并获得一个 constexpr 值:

template<size_t N>
class A{};

int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
A<std::get<0>(arg)> a_val;
}

这编译得很好。

  • 为什么检查函数没有正确检测到constexpr-ness?
  • 我该如何解决这个问题?

我在 Ubuntu 16.04 上用 Clang 3.8.0 测试了这个。

编辑:

作为基于 Sam 回答的进一步测试,我尝试了以下形式:

template<size_t N, class T>
auto check(const T& arg)
{
return sfinae_true<(std::get<N>(arg)*0)>();
}

这完全摆脱了逗号运算符,GCC 5.4.0 编译得很好,但 Clang 3.8.0 仍然提示。有趣的是,Clang 强调了 arg本身不是 constexpr。

为什么这个问题仍然存在? constexpr 函数参数的规则是什么?

最佳答案

这看起来像是一个编译器问题。

template<size_t N, class T>
auto check(const T& arg) -> sfinae_true<(std::get<N>(arg),N)>;

gcc 编译失败:

t.C:8:61: error: template argument 1 is invalid auto check(const T& arg) -> sfinae_true<(std::get(arg),N)>;

但是在稍微调整之后,我在 gcc 6.1.1 中得到了预期的结果:

#include <tuple>
#include <type_traits>
#include <iostream>

template<size_t> struct sfinae_true : std::true_type{};

template<size_t N, class T>
auto check(const T& arg)
{
return sfinae_true<(std::get<N>(arg),N)>();
}

template<size_t N, class>
std::false_type check(...);

int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
typedef decltype(check<0,decltype(arg)>(arg)) is_cexpr;
std::cout << "is constexpr? " << is_cexpr::value << '\n';
}

这导致:

is constexpr? 1

请注意,C++11 之前的常量表达式中不允许使用逗号。可能是那个时代遗留下来的东西……

关于c++ - 带 std::get 的 SFINAE constexpr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39163770/

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