我希望将常量从度数转换为弧度(在编译时),所以我选择使用constexpr.但是,我的程序不会编译,因此我尝试通过一些测试来调试问题.这些测试在编译期间继续产生错误.
当涉及许多有效数字时,该问题似乎与浮点算法相关.
我尝试了一个快速的谷歌搜索,我在Stroustrup的书中阅读了10.4节(常量表达式).任何帮助将不胜感激.我一定错过了一些明显的东西.
测试代码:
void testConstantExpressions() {
constexpr double x0 = 1.0;
constexpr double y0 = 2.0;
constexpr double z0 = 4.0;
constexpr double w0 = x0 / (y0 / z0);
std::cout << w0 << std::endl;
constexpr double x1 = 1.0;
constexpr double y1 = 2.2;
constexpr double z1 = 4.0;
constexpr double w1 = x1 / (y1 / z1);
std::cout << w1 << std::endl;
constexpr double x2 = 1.0;
constexpr double y2 = 4.0;
constexpr double z2 …Run Code Online (Sandbox Code Playgroud) 考虑以下具有单个数据成员和结构的结构 operator==
struct S {
int a;
/*constexpr*/ bool operator==(const S& other) const {
return this->a == other.a;
}
};
Run Code Online (Sandbox Code Playgroud)
在使用中,可以像constexpr初始化列表一样轻松创建两个结构
int main() {
constexpr S s1 = {1};
constexpr S s2 = {2};
constexpr bool b = s1 == s2; // error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
bool比较无法编译,因为==运算符未标记为constexpr,如果是,程序编译.
是否所有类别的比较运算符都constexpr可以标记为constexpr?我没有看到任何理由,但我也没有看到代码练习这个.
我还会更进一步,询问是否operator*(S, S)应该一直constexpr这样.
我想使用constexpr成员函数初始化constexpr成员变量,但它没有编译.当我把这个功能移出课堂时,没关系.为什么会这样?有没有办法使用类成员constexpr函数来初始化成员constexpr变量?
我正在使用Apple LLVM 8.0.0版(clang-800.0.38).
谢谢你的帮助.
constexpr static int Add_Ext(int a, int b) { return a + b; }
class Foo
{
public:
constexpr static int Add_InClass(int a, int b) { return a + b; }
// This is OK.
constexpr static int kConstantX = Add_Ext(1, 2);
// This results in a compile error.
constexpr static int kConstantY = Add_InClass(1, 2);
};
Run Code Online (Sandbox Code Playgroud)
clang错误信息:
Constexpr variable 'kConstantY' must be initialized by a constant expression
Run Code Online (Sandbox Code Playgroud) 有一个constexpr移动构造函数是否有意义?
例如,请考虑以下事项:
#include <array>
class C
{
public:
constexpr C(std::array<int, 3> ar) : m_ar{ar} {}
constexpr C(C&& other) : m_ar{std::move(other.m_ar)} { }
private:
std::array<int, 3> m_ar;
};
int main()
{
constexpr C c1 {{{1, 2, 3}}};
constexpr C c2{std::move(c1)};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这不编译,因为尽管调用std::move上c1,编译器推断它需要使用(隐含删除)拷贝构造函数,而不是移动构造函数.我不知道为什么.
但是如果我删除了constexprfrom c1,那么constexpr移动构造函数就会变得无法使用.
有没有办法让这个工作?或者这是一个constexpr移动构造函数的坏例子,但是有很好的例子吗?或者,拥有constexpr移动构造函数总是错误的吗?
我试图constexpr通过方法更改对象成员的值但我不明白为什么它不适用于这种特定情况:
#include <iostream>
struct test
{
int m_counter = 0;
constexpr test()
{
m_counter++;
m_counter++;
increment();
increment();
increment();
}
constexpr void increment()
{
m_counter++;
}
constexpr int value() const
{
return m_counter;
}
};
template<int value>
constexpr void check()
{
std::cout << value << std::endl;
}
// constexpr test t; // value = 3, why ?
int main()
{
constexpr test t; // value = 5, ok
check<t.value()>();
}
Run Code Online (Sandbox Code Playgroud)
当我在全局范围内创建对象时,我不明白为什么值为3.msvc和clang在两种情况下都显示5但不是gcc.谁错了?
以下代码给出了以下警告.有人可以解释一下原因(注意代码没有用,因为我用int替换了我的类型来制作一个完整的例子).
警告:' MaxEventSize()'函数使用' auto'类型说明符,不带尾随返回类型[默认启用]
我们的想法是获得特定结构的最大大小(类型去哪里int).
template<typename T>
constexpr T cexMax(T a, T b)
{
return (a < b) ? b : a;
}
constexpr auto MaxEventSize()
{
return cexMax(sizeof(int),
cexMax(sizeof(int),
sizeof(int)));
};
Run Code Online (Sandbox Code Playgroud) 我需要从constexpr结构中创建constexpr字节数组.
#include <array>
template<typename T>
constexpr std::array<uint8_t, sizeof(T)> o2ba(const T o) {
return {};
}
struct A {
int a;
};
int main() {
constexpr A x{ 1 };
constexpr auto y = o2ba(x); // y == { 0x01, 0x00, 0x00, 0x00 } for little endian
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我试图从联合中提取它:
template<typename T>
union U {
T o;
std::array<uint8_t, sizeof(T)> d;
};
template<typename T>
constexpr std::array<uint8_t, sizeof(T)> o2ba(const T o) {
return U<T>{o}.d;
}
Run Code Online (Sandbox Code Playgroud)
但它在gcc和msvc编译器上都无法访问d而不是初始化的o成员.它在初始化非constexpr对象时起作用,如下所示.
int main() {
constexpr A x{ …Run Code Online (Sandbox Code Playgroud) 我知道有一个针对constexpr()运算符的提议,但这尚未在gcc / clang中实现。我也知道使用一些技巧来实现,例如机器代码编辑:
http://saadahmad.ca/detecting-evaluation-context-inside-constexpr-functions/
我想知道是否有某种受限的解决方案:
struct F {
constexpr F(int v) {
if constexpr(constexpr()) {
static_assert(v > 0);
}
else {
assert(v > 0);
}
}
};
// ...
constexpr F f{0}; // should trigger a compile-time error
Run Code Online (Sandbox Code Playgroud)
我知道无法以这种方式使用static_assert,但这只是为了澄清问题。
以下是三次尝试实现is_constexpr()根据理查德·史密斯的回答到是is_constexpr可能在C ++ 11?
版本1
template <typename T>
bool constexpr is_constexpr_impl_1(const T& x, decltype(int{(x, 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_1(const T&, ...) { return false; }
template <typename T>
bool constexpr is_constexpr_1(const T& x) { return is_constexpr_impl_1(x, 0); }
Run Code Online (Sandbox Code Playgroud)
版本2
template <typename T>
bool constexpr is_constexpr_impl_2(const T& f, decltype(int{(f(0), 0u)})) { return true; }
template <typename T>
bool constexpr is_constexpr_impl_2(const T&, ...) { return false; }
template <typename T> …Run Code Online (Sandbox Code Playgroud) 让我们考虑一下这些简单的代码,它们只是尝试从constexpr数组初始化映射:
#include <string>
#include <map>
#include <array>
#include <tuple>
constexpr std::array<std::pair<int, const char *>, 10> my_array {
{ { 0, "dd" },
{ 1, "dd" },
{ 2, "dd" },
{ 7, "dd" },
{ 8, "dd" },
{ 9, "dd" }}
};
std::map<int, std::string> my_map(std::begin(my_array), std::end(my_array));
int main() {
return my_map[0].size(); //dummy random operation
}
Run Code Online (Sandbox Code Playgroud)
我知道没有办法预测两个变量(my_array和my_map)的初始化顺序。就是说,my_array是constexpr,因此应该在编译时可用,因此启动时应该没有“初始化顺序”问题。
这段代码正确还是初始化顺序问题仍然存在?