我想检查给定的double/float变量是否具有实际的位模式0x0.不要问为什么,它在qIsNull()我想成为的Qt()函数中使用constexpr.
原始代码使用了一个联合:
union { double d; int64_t i; } u;
u.d = d;
return u.i == 0;
Run Code Online (Sandbox Code Playgroud)
这constexpr当然不起作用.
接下来的尝试是reinterpret_cast:
return *reinterpret_cast<int64_t*>(&d) == 0;
Run Code Online (Sandbox Code Playgroud)
但是虽然它constexpr在GCC 4.7 中起作用,但它在Clang 3.1中失败(正确地,指针操作的b/c).
最后的想法是去Alexandrescuesque并做到这一点:
template <typename T1, typename T2>
union Converter {
T1 t1;
T2 t2;
explicit constexpr Converter( T1 t1 ) : t1(t1) {}
constexpr operator T2() const { return t2; }
};
// in qIsNull():
return Converter<double,int64_t>(d);
Run Code Online (Sandbox Code Playgroud)
但对于Clang来说,这也不够聪明:
note: read of member 't2' of …Run Code Online (Sandbox Code Playgroud) #include <exception>
constexpr bool foo(bool x)
{
return x ? true : throw std::exception();
}
int main()
{
// 1) must never be compiled
// static_assert(foo(false), "");
// 2) must always be compiled?
const bool x = foo(false);
// 3) must never compile?
constexpr bool y = foo(false);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我确信(1)必须导致编译错误.我很确定(2)在编译时不能被拒绝,尽管它会在运行时失败.
有趣的案例是constexpr变量(3).在这个简单的例子中,gcc和clang实际上会计算表达式,因此会拒绝该程序.(错误消息:y不是常量表达式).
每个C++ 11编译器都被迫拒绝该程序吗?如果foo(false)被更复杂的表达式替换怎么办?
我很惊讶地发现constexpr没有图灵完整,虽然它将在规范发生变化之后: 基于constexpr的计算Turing是否完整?
也许这与我的问题有关.据我所知,允许编译器推迟在本例中对constexpr(3)的实际评估,直到运行时.但是如果constexpr是turing-complete,我发现很难相信编译器可以决定是否所有constexpr都会抛出异常(这意味着constexpr无效).
我在g ++ 4.8.1和clang ++ 3.4的行为之间存在差异.
我有一个A文字类型的类,它有一个explicit constexpr转换函数可以输入enum class E.
Gcc允许我在某些情况下使用转换函数从constexpr类型E的常量表达式初始化类型A的变量,但不是在变量是静态类成员时(e2下面)
Clang拒绝所有上下文(e1,e2和e3)中的初始化.
根据[over.match.conv]p1使用显式转换功能可以在这里
enum class E { e };
struct A { explicit constexpr operator const E() const noexcept { return E::e; } };
constexpr E e1{A{}}; // Gcc: OK, Clang: Error
struct B { static constexpr E e2{A{}}; }; // Gcc: Error, Clang: Error
void f() { static …Run Code Online (Sandbox Code Playgroud) 我正在验证关于C++ Primer的声明:
Unlinke其他函数,inline和constexpr函数可以在程序中多次定义.
我cfunc()在下面使用了constexpr的两个定义,期望foo_0()将调用第一个def同时foo_1()调用第二个def.但是,尝试失败并出现编译错误(最后).为什么?
constexpr int cfunc(){
return 42;
}
int foo_0(){
return cfunc();
}
constexpr int cfunc(){
return 42;
}
int foo_1(){
return cfunc();
}
int main(int argc, char **argv) {
cout << foo_0() << endl;
cout << foo_1() << endl;
/* testconstexprfunc2.cpp:24:15: error: redefinition of ‘constexpr int cfunc()’ */
/* testconstexprfunc2.cpp:16:15: error: ‘constexpr int cfunc()’ previously defined here */
return 0;
}
Run Code Online (Sandbox Code Playgroud) 为什么下面的工作原理gcc却没有clang,(现场观看):
constexpr int giveMeValue() { return 42; }
struct TryMe {
static constexpr int arr[1] = {
giveMeValue()
};
};
int main() {
int val = TryMe::arr[0];
return val;
}
Run Code Online (Sandbox Code Playgroud)
我得到一个未解决的外部符号与clang.
是TryMe::arr[0]一个对象?如果是的话,它是否经常使用?
我有一个带有constexpr值构造函数的类,但没有复制或移动ctor
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
};
int main() {
constexpr C arr[] = {1, 2};
}
Run Code Online (Sandbox Code Playgroud)
我发现这段代码不起作用,因为它实际上是试图使用移动构造函数C而不是值构造函数来构造.一个问题是我希望这个对象不可移动(出于测试目的),但我认为"好吧,好吧,我会添加一个移动构造函数."
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
C& operator=(C&&) = delete;
C(C&&) { /*something*/ } // added, assume this must be non trivial
};
Run Code Online (Sandbox Code Playgroud)
好的,现在它使用移动构造函数,一切都在gcc下运行但是当我使用clang时,它会抱怨因为移动构造函数没有标记constexpr
error: constexpr variable 'arr' must be initialized by …Run Code Online (Sandbox Code Playgroud) 我最近开始在我的代码中使用更多的C++ 11功能,我一直想知道constexpr关键字的位置是否与常量类型之前或之后不同.
风格1:
constexpr int FOO = 1;
constexpr auto BAR = "bar";
Run Code Online (Sandbox Code Playgroud)
风格2:
int constexpr FOO = 1;
auto constexpr BAR = "bar";
Run Code Online (Sandbox Code Playgroud)
样式2是我喜欢放置const关键字的方式,constexpr以相同的方式放置会给代码带来一些一致性.然而,这被认为是不好的做法,或者风格2还有其他问题,因为我并没有真正看到有人这样写.
目前我正在重写/扩展我的C++实用程序库,考虑新的C++ 11功能.其中一个新增功能是一个模板类,它可以在编译时提供一组数字的最大值.
template<typename T, T... Xs> class ConstMax
{
private:
template<typename... Ts> static constexpr T Max(Ts... xs);
template<typename Tx> static constexpr T Max(Tx x)
{
return x;
}
template<typename T1, typename T2, typename... Ts> static constexpr T Max(T1 x, T2 y, Ts... xs)
{
return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...);
}
public:
static const T Value = Max(Xs...);
};
Run Code Online (Sandbox Code Playgroud)
此类的示例用法:
int max = ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value;
Run Code Online (Sandbox Code Playgroud)
这里有另一个例子可能会让我更难以验证在编译期间是否实际评估了ConstMax <...> :: …
#include<iostream>
using namespace std;
template<int N> class Prime
{ // generate N prime numbers at compile time
public:
unsigned int arr[N]{};
constexpr Prime() {
int k=0;
for(unsigned int i=2; k<N; i++) {
bool isPrime = true;
for(int j=0; j<k; j++) {
if(arr[j] > i/2) break;
if(i % arr[j] == 0) {
isPrime = false;
break;
}
}
if(isPrime) arr[k++] = i;
}
}
};
int main()
{
Prime<50000> prime; // if 50000->5000, ok
for(auto& a : prime.arr) cout << a …Run Code Online (Sandbox Code Playgroud) c++ templates compiler-errors compile-time-constant constexpr
大多数C++编译器都支持SIMD(SSE/AVX)指令
_mm_cmpeq_epi32
Run Code Online (Sandbox Code Playgroud)
我的问题是这个函数没有标记为constexpr,虽然"语义上"没有理由不使用这个函数,constexpr因为它是一个纯函数.
有什么办法,我可以写我自己的版本(例如)_mm_cmpeq_epi32是constexpr?
显然我希望运行时的函数使用正确的asm,我知道我可以重新实现具有慢速函数的任何SIMD函数constexpr.
如果你想知道为什么我关心constexprSIMD功能.非constexprness具有传染性,这意味着我的任何使用SIMD功能的功能都不可能constexpr.