相关疑难解决方法(0)

什么时候constexpr函数在编译时得到评估?

由于在运行时可能会调用声明为constexpr的函数,编译器在哪个条件下决定是在编译时还是在运行时计算它?

template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
    return (expo != 0 )? base * POW(base, expo -1) : 1;
}

int main(int argc, char** argv)
{
    int i = 0;
    std::cin >> i;

    std::cout << POW(i, 2) << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我在编译时是未知的,这可能是编译器将POW()视为在运行时调用的常规函数​​的原因.然而,这种动态虽然看起来很方便,但却具有一些不切实际的含义.例如,是否有一种情况我希望编译器在编译时计算constexpr函数,编译器决定将其视为普通函数,而它在编译时也会工作?有任何已知的常见陷阱吗?

c++ runtime compile-time constexpr c++11

58
推荐指数
2
解决办法
1万
查看次数

C++ 11 - constexpr函数中的static_assert?

如何static_assert在一个constexpr函数中正确执行?例如:

constexpr int do_something(int x)
{
  static_assert(x > 0, "x must be > 0");
  return x + 5;
}
Run Code Online (Sandbox Code Playgroud)

这不是有效的C++ 11代码,因为constexpr函数必须只包含return语句.我不认为该标准有例外,但GCC 4.7不允许我编译这段代码.

c++ static-assert constexpr c++11

53
推荐指数
2
解决办法
1万
查看次数

在C++ 11标准中,它指定何时可以在翻译期间评估constexpr函数?

仅仅因为一个函数(或构造函数)......

  • 宣布constexpr和
  • 函数定义符合constexpr要求

...并不意味着编译器将在转换期间评估constexpr函数.我一直在查看C++ 11 FDIS(N3242,可从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/获取)来尝试确定两件事:

  • 什么时候编译器有义务在翻译期间评估constexpr函数?
  • 编译器何时允许在翻译期间评估constexpr函数?

第5.19节第1段说明在翻译过程中可以评估常量表达式.据我所知,第5.19节的其余部分阐述了constexpr函数定义中有效的规则.

我理解我可以通过将constexpr函数的结果声明为constexpr来强制转换期间的constexpr评估.像这样:

// Declaration
constexpr double eulers_num() { return 2.718281828459045235360287471; }

// Forced evaluation during translation
constexpr double twoEulers = eulers_num() * 2.0;
static_assert(twoEulers > 5.0, "Yipes!");
Run Code Online (Sandbox Code Playgroud)

到目前为止,我一直无法找到FDIS中的段落:

  • twoEulers在翻译过程中要评估的力量
  • 在编译器可能或必须在转换期间评估constexpr函数时指定其他情况.

我对发现特别感兴趣的是翻译期间的constexpr评估是否由以下因素触发:

  1. 当传递给constexpr函数的所有参数都是文字,或者
  2. 隐含对象参数重载方案(13.3.1节第3段)期间或者是constexpr或需要一个文字(例如用于阵列的尺寸),或
  3. 还有别的东西.

如果可能的话,请在您的回复中引用我可以查找的FDIS部分或我可以在FDIS中搜索的关键短语.标准中的英语有点迟钝,所以我可能已经阅读了相关的段落并完全忽略了它们的含义或意图.

c++ constexpr c++11

18
推荐指数
2
解决办法
676
查看次数

什么是'constexpr'有用?

我真的找不到任何用途.我的第一个想法是,我可以使用它来实现'按合同设计',而不使用像这样的宏:

struct S
{   
    S(constexpr int i) : S(i) { static_assert( i < 9, "i must be < 9" ); }

    S(int i); //external defintion

    char *pSomeMemory;
};
Run Code Online (Sandbox Code Playgroud)

但这不会编译.我想我们也可以使用它来引用同一变量,而不需要创建额外的内存,当我们想要避免get/setters时,为了使用户的一个成员的实例是只读的:

class S
{  
private:
    int _i;

public:
    const int & constexpr i = _i;
};
Run Code Online (Sandbox Code Playgroud)

但以上都没有实际编译过.有人可以告诉我为什么要引入这个关键字?

c++ compile-time language-lawyer c++11

15
推荐指数
3
解决办法
4076
查看次数

强制在编译期间评估常量表达式?

几天前,我询问编译器决定是否在编译期间计算constexpr函数.

什么时候constexpr函数在编译时得到评估?

事实证明,只有在编译时才会评估constexpr,如果所有参数都是常量表达式,并且您指定给它的变量也是常量表达式.

template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
    return (expo != 0 )? base * POW(base, expo -1) : 1;
}

template<typename T>
void foobar(T val)
{
    std::cout << val << std::endl;
}

int main(int argc, char** argv)
{
    foobar(POW((unsigned long long)2, 63));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我被告知是真的,这个代码示例是非常不实际的,因为foobar不接受constexpr(由于某种原因你不能使用consexpr作为参数),POW在运行时被评估,即使它可能是可能的在编译期间计算它.强制编译时评估的明显解决方案是:

auto expr = POW((unsigned long long)2, 63);
foobar(expr);
Run Code Online (Sandbox Code Playgroud)

然而,这迫使我使用额外的代码行,每次我想确保在编译时评估constexpr时都不需要这样做.为了使这更方便一点,我想出了以下可疑的宏:

#define FORCE_CT_EVAL(func) [](){constexpr auto ___expr = func; return std::move(___expr);}()
foobar(FORCE_CT_EVAL(POW((unsigned long long)2, 63)));
Run Code Online (Sandbox Code Playgroud)

尽管它工作得很好,但我觉得好像有些不对劲.创建匿名lambda会影响性能吗?通过rvalue引用返回实际上是将表达式移动到函数参数吗?std :: move如何影响性能?有没有更好的单线解决方案呢?

c++ evaluation compile-time constexpr c++11

11
推荐指数
1
解决办法
2084
查看次数

将任何函数作为模板参数传递?

我正在寻找一种方法将通用(constexpr,显然)功能传递给模板.它必须能够在不使用lambda的情况下获取任何数量的参数.这是我到目前为止:

template<typename T, T(*FUNC)()> struct CALL
{
    static inline constexpr decltype(FUNC()) EXEC()
    {
        return FUNC();
    }
};
Run Code Online (Sandbox Code Playgroud)

但是,只有传递的函数不带参数时才有效.有没有办法让模板接受任何constexpr功能?传递std ::函数似乎不起作用.我想关键是可变参数模板参数,但我不知道在这种情况下如何利用它们.

c++ templates function-pointers variadic-templates c++11

2
推荐指数
1
解决办法
946
查看次数