标签: constexpr

constexpr函数评估可以进行尾递归优化

我想知道对于长循环我们是否可以在C++ 11中利用constexpr的尾递归?

c++ language-lawyer constexpr c++11

15
推荐指数
1
解决办法
4804
查看次数

在constexpr抛出的异常中使用副作用是否合法?

通常,constexpr必须没有副作用.但是,我刚刚发现可以在抛出异常的构造函数中使用副作用.该技术可用于模拟constexpr函数的assert(),如下面的程序所示.

#include <iostream>
#include <cstdlib>
#include <stdexcept>

struct constexpr_precond_violated : std::logic_error
{
  constexpr_precond_violated(const char* msg) :
    std::logic_error(msg)
  {
    std::cerr << msg << '\n';
    abort(); // to get a core dump
  }
};

#define TO_STRING_IMPL(x) #x
#define TO_STRING(x) TO_STRING_IMPL(x)

#define CONSTEXPR_PRECOND(cond, value) \
  ((!(cond)) ? throw constexpr_precond_violated( \
    "assertion: <" #cond "> failed (file: " \
    __FILE__ ", line: " TO_STRING(__LINE__) ")")    \
   : (value))

constexpr int divide(int x, int y)
{
  return CONSTEXPR_PRECOND(y != 0, x / y);
}

int …
Run Code Online (Sandbox Code Playgroud)

c++ assert language-lawyer constexpr c++11

15
推荐指数
1
解决办法
732
查看次数

关于常量表达式的困惑

这是本主题的某种后续行动,涉及其中的一小部分.与前一个主题一样,让我们​​考虑一下我们的编译器有和的constexpr函数.现在,让我们直截了当地说.std::initializer_liststd::array

这有效:

#include <array>
#include <initializer_list>

int main()
{
    constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
    constexpr int a0 = a[0];
    constexpr int a1 = a[1];
    constexpr int a2 = a[2];
    constexpr std::initializer_list<int> b = { a0, a1, a2 };

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这不是:

#include <array>
#include <initializer_list>

int main()
{
    constexpr std::array<int, 3> a = {{ 1, 2, 3 }};
    constexpr std::initializer_list<int> b = { a[0], a[1], a[2] …
Run Code Online (Sandbox Code Playgroud)

c++ compile-time constant-expression constexpr c++11

15
推荐指数
1
解决办法
2418
查看次数

constexpr函数的未定义符号

当我尝试编译以下代码时,我得到一个链接器错误:Undefined symbols for architecture x86_64: "Foo()", referenced from: _main in main.o使用LLVM 4.2.

仅在标记函数时才会出现此问题constexpr.当标记功能时,程序会正确编译和链接const.为什么声明该函数constexpr会导致链接器错误?

(我意识到以这种方式编写函数不会带来编译时计算的好处;此时我很好奇为什么函数无法链接.)

main.cpp中

#include <iostream>
#include "test.hpp"

int main()
{
    int bar = Foo();
    std::cout << bar << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

test.hpp

constexpr int Foo();
Run Code Online (Sandbox Code Playgroud)

TEST.CPP

#include "test.hpp"

constexpr int Foo()
{
    return 42;
}
Run Code Online (Sandbox Code Playgroud)

c++ linker-errors constexpr c++11

15
推荐指数
2
解决办法
1698
查看次数

constexpr类的全球类型

我的理解是constexpr类类型的全局变量几乎无法使用,因为

  • 必须在每个TU中定义这样的对象,因为constexpr不允许对象的前向声明.

  • 默认链接static会导致在内联函数中命名对象(ODR使用与否)以违反ODR,因为相应的inline定义具有不同的含义.

  • extern constexpr如果对象是ODR使用的,则每个TU的一个定义的声明将违反ODR规则,这在对其进行引用时发生.

    • 引用隐式this参数,即使它已被成员函数使用.
    • 如果您尝试通过引用传递对象,显然会发生这种情况.
    • 如果您尝试按值传递对象也会发生这种情况,该值隐式使用副本或移动构造函数,根据定义,它通过引用传递.
    • 如果extern constexpr即使没有使用ODR,也会声明对象,GCC和Clang都会抱怨ODR违规(多个定义).

这都是正确的吗?有没有办法让一个constexpr全局类类型没有包装在一个inline函数中?

c++ global one-definition-rule constexpr c++11

15
推荐指数
1
解决办法
1000
查看次数

什么时候应该将构造函数设置为constexpr?

我知道c ++ 11允许使用constexpr为编译时而不是运行时指定表达式.

我知道这也可以用于类的构造函数.但是,此构造函数必须初始化类的所有成员,以便用作constexpr(在编译时),并且它调用的任何函数也应标记为constexpr.

但是什么时候会将他的构造函数设置为constexpr,除了轻微优化之外还有其他任何好处吗?

这是否意味着,如果我可以,我应该总是将我的构造函数设置为constexpr?

c++ constexpr c++11

15
推荐指数
1
解决办法
703
查看次数

虚函数可以是constexpr吗?

可以X::f()在下面的代码中使用虚函数

struct X 
{
    constexpr virtual int f() const 
    {
        return 0;
    }
};
Run Code Online (Sandbox Code Playgroud)

constexpr吗?

c++ virtual-functions constexpr c++11

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

在C++ 17之前/之后的constexpr静态成员

据我所知,一个非常常见的情况是这样的

template<int i> class Class
{
public:
    static constexpr int I = i;
    static constexpr int J = constexprFunction(i);
    // further Class implementation
};
Run Code Online (Sandbox Code Playgroud)

几乎同样普遍的我看到错误(事实上我的大部分问题是因为我忘记了,并且不知道,正确的问题是什么)如果成员使用的话会忘记附加的定义:

template<int i> constexpr int Class<i>::I;
template<int i> constexpr int Class<i>::J;
Run Code Online (Sandbox Code Playgroud)

现在我读了cppreference:Definitions和ODR以及cppreference:静态成员,声明这是C++ 17不推荐使用的.这对我来说似乎很棒,因为它避免了很多错误.但是还有其他问题出现了:

1)这改变了其他原因,而不是使附加定义无用吗?(另见本问题的最后一段)

2)在cppreference的最后一个例子中:静态成员似乎也适用于const static成员 - 但规则只声明了constexpr成员.是否适用于const static会员?

3)所有的例子,我发现用一个简单的定义一样Class::I-做这一切还保持了形势Class:Jconstexpr功能?

简要说明在C++ 17和C++ 17之前最佳实践是什么.总而言之,这对我来说似乎是一个非常棘手的变化,因为它会产生很多代码,这些代码之前需要"格式化不需要诊断"才能获得良好的代码(据我所知......).因此,会产生代码,对于较早的(前17版)编译器仍然是"不需要的非诊断" - 但只要不需要使用odr,这些就不会抱怨.

编辑:更正了Aaron McDaid建议的文字.

c++ static constexpr c++17

15
推荐指数
1
解决办法
1344
查看次数

如何声明constexpr C字符串?

我想我非常理解如何将关键字constexpr用于简单的变量类型,但是当涉及到指向值的指针时,我感到很困惑.

我想声明一个constexpr C字符串文字,它的行为就像

#define my_str "hello"
Run Code Online (Sandbox Code Playgroud)

这意味着编译器将C字符串文字插入到我输入此符号的每个位置,并且我将能够在编译时使用sizeof获取其长度.

是吗 constexpr char * const my_str = "hello";

要么 const char * constexpr my_str = "hello";

要么 constexpr char my_str [] = "hello";

还是还有别的什么?

c++ c-strings string-literals constexpr

15
推荐指数
2
解决办法
8202
查看次数

使用派生类的静态constexpr数据成员初始化基类的静态constexpr数据成员

请考虑以下代码:

template<typename T>
struct S { static constexpr int bar = T::foo; };

struct U: S<U> { static constexpr int foo = 42; };

int main() { }
Run Code Online (Sandbox Code Playgroud)

GCC v6.1编译它,clang 3.8拒绝它并带有错误:

2:错误:'U'
结构中没有名为'foo'的成员S {static constexpr int bar = T :: foo; };

哪个编译器是对的?
可能是因为我们尝试在其中使用它时U 不是一个完整的类型S吗?
在这种情况下,它应该被认为是GCC的一个错误,但我想知道我是否正好在bug跟踪器上搜索/打开一个问题...

编辑

与此同时,我向GCC 打开了一个错误.
等待它接受答案.

c++ templates crtp constexpr c++14

14
推荐指数
1
解决办法
1580
查看次数