有没有办法在编译时打印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 …
仅仅因为一个函数(或构造函数)......
...并不意味着编译器将在转换期间评估constexpr函数.我一直在查看C++ 11 FDIS(N3242,可从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/获取)来尝试确定两件事:
第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评估是否由以下因素触发:
如果可能的话,请在您的回复中引用我可以查找的FDIS部分或我可以在FDIS中搜索的关键短语.标准中的英语有点迟钝,所以我可能已经阅读了相关的段落并完全忽略了它们的含义或意图.
我遇到以下代码时遇到问题:
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,它具有类型的非类型但引用模板参数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 …
我对static constexprC++ 11中的成员变量有一些疑惑.
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)
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,我有:
// empty struct
template<typename T> …Run Code Online (Sandbox Code Playgroud) 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的东西会更好,但目前这是不可能的.)
我想使用constexpr的标准版<cmath>一样的功能exp,log,pow在便携方式.我目前有一个非便携式解决方案g++将这些功能视为constexpr- 不兼容C++的扩展,但我担心可移植性和面向未来(我想这个扩展可能有一天会被删除g++).
我constexpr对这些函数的版本感兴趣,而不是模板元程序 - 我希望在编译时和运行时都可以使用相同的功能.我不需要C兼容性,但我确实需要快速实现 - 诸如Taylor Series扩展之类的天真实现会太慢.
我该如何实现这些功能?我在特别感兴趣exp,log和pow
我从研究中学到了一些切向相关的东西
constexpr因为它们必须具有副作用(例如设置errno)以保持C兼容性constexpr,但作为C++ 14,这是禁止的(每个第一回答这个问题和回答这个问题).这是我担心函数可能不会出现constexpr在以后版本中的部分原因g++g++每个数学函数的实现foo只调用一个内置函数__builtin_foo,它被视为constexpr.我或许可以开始调用__builtin_foo函数而不是foo函数 - 即使相应的函数符合要求,这些函数仍可能保留constexpr在未来版本中- 但这只会有助于未来验证,而不是可移植性.g++foo以下代码:
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++ 吗?
我的猜测是它应该是有效的,因为 …
我对一个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,以上所有都正常工作.
虽然我之前使用过这样的代码,但很明显编译器有足够的信息可以工作,但我真的不明白为什么这会编译:
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)