标签: constexpr

编译时的std :: cout等效,或者c ++ 11中编译时常量值的static_assert字符串化

有没有办法在编译时打印a constexpr#defined值的值?我想要相当于std::cout <<或某种方式来做类似的事情

constexpr int PI_INT = 4;
static_assert(PI_INT == 3,
              const_str_join("PI_INT must be 3, not ", const_int_to_str(PI_INT)));
Run Code Online (Sandbox Code Playgroud)

编辑:我可以用constexprs 做一些基本的编译时打印,至少在gcc上做类似的事情

template <int v>
struct display_non_zero_int_value;

template <>
struct display_non_zero_int_value<0> { static constexpr bool foo = true; };

static constexpr int v = 1;

static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");
Run Code Online (Sandbox Code Playgroud)

这给了我error: incomplete type ‘display_non_zero_int_value<1>’ used in nested name specifier static_assert(v == 0 && display_non_zero_int_value<v>::foo, "v == 0");.(另一方面,icpc不太有帮助,只是说error: incomplete …

c++ cout static-assert constexpr c++11

18
推荐指数
1
解决办法
3496
查看次数

在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

我遇到以下代码时遇到问题:

template<typename T>
constexpr int get(T vec) {
  return vec.get();
}

struct coord {
  constexpr int get() const { return x; }
  int x;
};

struct foo {
    struct coord2 {
      constexpr int get() const { return x; }
      int x;
    };
    constexpr static coord f = { 5 };
    constexpr static int g = get(f); // works

    constexpr static coord2 h = { 5 };
    constexpr static int i = get(h); // doesn't work
};

constexpr coord foo::f;
constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++11

18
推荐指数
1
解决办法
375
查看次数

使用constexpr函数失败的模板实例化

我有一个模板类C,它具有类型的非类型但引用模板参数P:

class P {
public:
  int x;
  int y;
};

template <const P &x>
class C {
public:
  const int &f() { return x.x; }
};
Run Code Online (Sandbox Code Playgroud)

我声明了一个类型的全局变量P:

P p = {33,44};
Run Code Online (Sandbox Code Playgroud)

我还声明了一个返回引用的函数p:

constexpr const P &h() { return p; }
Run Code Online (Sandbox Code Playgroud)

然后尝试在下面使用这些:

C<p> o;    // line 1
C<h()> oo; // line 2
Run Code Online (Sandbox Code Playgroud)

当然我对第一次实例化没有问题,但第二次实例化没有问题.我的编译器抱怨:

error: non-type template argument does not refer to any declaration
Run Code Online (Sandbox Code Playgroud)

为什么会这样?我无法在常规中找到反对它的论据.我不确定它是否与在默认模板参数调用constexpr完全相同的问题,其中讨论是关于嵌套 instanciation的实例化点.这是一个类型问题,但哪一个?我的函数h()返回对定义良好的类型(const …

c++ templates language-lawyer constexpr c++11

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

了解静态constexpr成员变量

我对static constexprC++ 11中的成员变量有一些疑惑.

在first.hpp中

template<typename T>
struct cond_I
{ static constexpr T value = 0; }; 


// specialization 
template<typename T>
struct cond_I< std::complex<T> >
{ static constexpr std::complex<T> value = {0,1}; }; 
Run Code Online (Sandbox Code Playgroud)

在main()函数中

cout << cond_I<double>::value << endl;            // this works fine
cout << cond_I< complex<double> >::value << endl; // linker error
Run Code Online (Sandbox Code Playgroud)

但是,如果我添加以下行,first.hpp一切正常.

template<typename T1> 
constexpr std::complex<T1> cond_I< std::complex<T1> >::value;
Run Code Online (Sandbox Code Playgroud)

我理解的(我可能是错的)是,cond_I< std::complex<double> >::value需要一个定义,但在前一种情况下它只有声明.但那又怎么样cond_I<double>::value?为什么它不需要定义?

再次,在另一个头文件中second.hpp,我有:

在second.hpp中

// empty struct
template<typename T> …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++11

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

Constexpr放置新品?

C++标准特别禁止调用new常量表达式(N4296第5.20节[expr.const]):

条件表达式e是核心常量表达式,除非根据抽象机器(1.9)的规则评估e将评估以下表达式之一:

...

- 一个新表达式(5.3.4);

这项禁令(据我所知)延伸到所有形式new,包括新的安置.但是,由于placement new实际上并没有分配任何内存,只是在给定位置运行构造函数,并且因为在constexpr上下文中获取变量的地址是合法的(事实上​​,std::addressof在C++ 17中将是constexpr),似乎对我来说,这个禁令(原则上至少)可以放宽,以允许在constexpr功能中放置新的禁令.

所以我的问题是,我错过了什么吗?有没有一个很好的理由为什么在constexpr功能中禁止放置新的?

(对于上下文:当前规则几乎要求启用constexpr的sum类型std::variant实现为递归联合.能够使用类似std::aligned_storage和贴片new的东西会更好,但目前这是不可能的.)

c++ placement-new language-lawyer constexpr

18
推荐指数
1
解决办法
1215
查看次数

constexpr exp,log,pow

我想使用constexpr的标准版<cmath>一样的功能exp,log,pow在便携方式.我目前有一个非便携式解决方案g++将这些功能视为constexpr- 不兼容C++的扩展,但我担心可移植性和面向未来(我想这个扩展可能有一天会被删除g++).

constexpr对这些函数的版本感兴趣,而不是模板元程序 - 我希望在编译时和运行时都可以使用相同的功能.我不需要C兼容性,但我确实需要快速实现 - 诸如Taylor Series扩展之类的天真实现会太慢.

我该如何实现这些功能?我在特别感兴趣exp,logpow

我从研究中学到了一些切向相关的东西

  • 这些功能的标准兼容版本在技术上并不是constexpr因为它们必须具有副作用(例如设置errno)以保持C兼容性
  • 在C++ 11,一种实现被允许进行这些功能constexpr,但作为C++ 14,这是禁止的(每个第一回答这个问题回答这个问题).这是我担心函数可能不会出现constexpr在以后版本中的部分原因g++
  • g++每个数学函数的实现foo只调用一个内置函数__builtin_foo,它被视为constexpr.我或许可以开始调用__builtin_foo函数而不是foo函数 - 即使相应的函数符合要求,这些函数仍可能保留constexpr在未来版本中- 但这只会有助于未来验证,而不是可移植性.g++foo

c++ language-lawyer constexpr c++11

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

类范围内的 constexpr 变量的初始值设定项是否允许引用该变量?

以下代码:

struct S {
    static constexpr int rolling_sum[4]{
        0,
        rolling_sum[0] + 1,
        rolling_sum[1] + 2,
        rolling_sum[2] + 3
    };
};
Run Code Online (Sandbox Code Playgroud)

被 clang 接受(用版本 12 测试),但被 gcc(用版本 11 测试)拒绝,并出现以下错误:

test.cpp:4:9: error: ‘rolling_sum’ was not declared in this scope
    4 |         rolling_sum[0] + 1,
      |         ^~~~~~~~~~~
test.cpp:5:9: error: ‘rolling_sum’ was not declared in this scope
    5 |         rolling_sum[1] + 2,
      |         ^~~~~~~~~~~
test.cpp:6:9: error: ‘rolling_sum’ was not declared in this scope
    6 |         rolling_sum[2] + 3
      |         ^~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

这段代码是有效的 C++ 吗?

我的猜测是它应该是有效的,因为 …

c++ language-lawyer constexpr c++14

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

什么是C++中的constexpr?

我对一个constexpr概念感到困惑,因为我读过的constexpr是在编译时进行评估,因此它对于性能优化与正常情况相比非常有用const.

constexpr int i = 0;
constexpr int& ri = i;
Run Code Online (Sandbox Code Playgroud)

上面的代码返回一个错误"从'const int'类型的表达式中无效初始化类型'int&'的引用",为什么?

此外,下一个代码有一个错误:

constexpr int i = 0;
constexpr int* ri = &i;
Run Code Online (Sandbox Code Playgroud)

如果我替换了constexpr关键字const,以上所有都正常工作.

c++ const constexpr

17
推荐指数
3
解决办法
2122
查看次数

通过值传递的积分常数,被视为constexpr?

虽然我之前使用过这样的代码,但很明显编译器有足够的信息可以工作,但我真的不明白为什么这会编译:

template <class T, class I>
auto foo(const T& t, I i) {
    return std::get<i>(t);
}

int main()
{
    std::cerr << foo(std::make_tuple(3,4), std::integral_constant<std::size_t, 0>{});
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

实例:http://coliru.stacked-crooked.com/a/fc9cc6b954912bc5.

似乎可以同时使用gcc和clang.的事情是,同时integral_constant具有constexpr转换所存储的整数,constexpr成员函数隐式地把对象本身作为参数,并且因此不能被用在这样的函数constexpr的上下文,除非我们正在呼叫的成员函数的对象本身可以作为被处理constexpr.

这里i是一个传递给的参数foo,因此i绝对不能被视为constexpr.然而,确实如此.一个更简单的例子:

template <class I>
void foo(I i) {
    constexpr std::size_t j = i;
}
Run Code Online (Sandbox Code Playgroud)

这也是编译,只要std::integral_constant<std::size_t, 0>{}传递给foo.

我觉得我错过了一些关于constexpr规则的明显内容.无状态类型或其他类型是否有例外?(或者,也许是两个主要编译器中的编译器错误?这个代码似乎适用于clang 5和gcc 7.2).

编辑:答案已经发布,但我认为这还不够.特别是,鉴于最后的定义foo,为什么:

foo(std::integral_constant<std::size_t, …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++14

17
推荐指数
2
解决办法
1197
查看次数