当前位置: 首页 > 知识库问答 >
问题:

SFINAE constepr与std::get

张亦
2023-03-14

这是用SFINAE检测constepr的后续问题。

我想检测元组的一个元素(或任何可以与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!为了检查是否由于某些原因没有总是调用假重载,我注释掉了假重载并得到了编译器错误:

注意:已忽略候选模板:替换失败[N=0,T=const std::tuple]:非类型模板参数不是常量表达式
自动检查(const T

但是,我确实知道我可以调用std::获取

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

这编译得很好。

  • 为什么检查函数不能正确检测到conexpr-ness?
  • 我该怎么解决这个问题?

我在Ubuntu 16.04上用Clang3.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函数参数的规则是什么?


共有1个答案

程卓君
2023-03-14

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

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

gcc未能编译以下内容:

t、 C:8:61:错误:模板参数1是无效的自动检查(const t

但是在稍微调整了一下之后,我在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之前的常量表达式中不允许使用逗号。可能是那个时代遗留下来的东西。。。

 类似资料:
  • 错误:无法将类型为“std::_bit_reference&”的非常量lvalue引用绑定到类型为“std::vector::reference”{aka“std::_bit_reference”}的rvalue 因此,它抱怨,因为只有第二个参数是rvalue

  • 多亏了C11,我们收到了系列的仿函数包装器。不幸的是,我一直只听到关于这些新添加的不好的消息。最受欢迎的是它们非常慢。我测试了它,与模板相比,它们真的很糟糕。 111毫秒对1241毫秒。我认为这是因为模板可以很好地内联,而通过虚拟调用覆盖内部。 显然,在我看来,模板也有其问题: 它们必须以头的形式提供,这不是您在以封闭代码形式发布库时可能不希望做的事情, 因此,我可以假设s可以用作传递函子的事实标

  • 问题内容: 我尝试将matlab代码转换为numpy,并发现numpy与std函数的结果不同。 在matlab中 在numpy中 这正常吗?我应该如何处理呢? 问题答案: NumPy函数采用一个可选参数:“自由度增量”。默认情况下是。对其进行设置以获取MATLAB结果: 要添加更多上下文,在计算方差(标准偏差为平方根)时,通常将其除以我们拥有的值的数量。 但是,如果我们从较大的分布中选择元素的随机

  • 我试图创建一个查找表,以便轻松创建具有不同值的对象。为此,我需要在类中使用一个静态std::数组填充数据。目前看起来是这样的: 它工作正常,如果我删除std::字符串,但与std::字符串我得到编译错误

  • 我在理解条件变量及其在互斥体中的使用时遇到了一些困难,我希望社区能帮助我。请注意,我来自win32背景,因此与CRITICAL_SECTION、HANDLE、SetEvent、WaitForMultipleObject等一起使用。 这是我第一次尝试使用C++11标准库进行并发操作,它是在这里找到的一个程序示例的修改版本。 关于这个的几个问题。 我读过“任何要等待std::condition_var