我想检查给定的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) 编辑:在最初的问题中有一个错误的公式,并且尝试的算法正在做一些与预期完全不同的事情.我道歉,我决定重写这个问题,以消除所有的困惑.
我需要在编译时计算(结果将用作非类型模板参数)存储n不同状态所需的最小位数:
constexpr unsigned bitsNeeded(unsigned n);
Run Code Online (Sandbox Code Playgroud)
或通过模板
结果应该是:
+-----------+--------+
| number of | bits |
| states | needed |
+-----------+--------+
| 0 | 0 | * or not defined
| | |
| 1 | 0 |
| | |
| 2 | 1 |
| | |
| 3 | 2 |
| 4 | 2 |
| | |
| 5 | 3 |
| 6 | 3 |
| 7 | …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]一个对象?如果是的话,它是否经常使用?
我最近开始在我的代码中使用更多的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
假设我有一个编译时constexpr数组和一个可变参数类模板,其中包含一组与数组元素相同类型的非类型参数.
我的目标是使用数组中的值实例化类模板:
struct Container
{
int containee[3];
};
constexpr Container makeContainer();
template <int... Elements> class Foo;
Foo<makeContainer().containee[0],
makeContainer().containee[1],
makeContainer().containee[2]> foo;
Run Code Online (Sandbox Code Playgroud)
上面的代码效果很好.但是,每当我需要实例化Foo模板时,我都不得不手动索引数组.我想编译器自动为我做这件事:
Foo<Magic(makeContainer().containee)> foo;
Run Code Online (Sandbox Code Playgroud)
我在cppreference做了一些RTFM,但这没有帮助.我知道std::forward<>(),但它不能应用于模板参数列表.
c++ templates template-meta-programming variadic-templates constexpr
我抓我的头std::optional,而根据该文档,不应该有一个constexpr赋值运算符.
但是,当我在gcc-8.1中尝试这个片段时,它编译并正常工作:
constexpr std::optional<int> foo() {
std::optional<int> bar = 3;
bar = 1337;
return bar;
}
constexpr auto z = foo();
Run Code Online (Sandbox Code Playgroud)
有什么我想念的吗?
所有std :: span的构造函数都声明为constexpr,但是我似乎无法在constexpr上下文中使用它们中的任何一个。取消注释以下任何constexpr都将导致编译错误。
#include <array>
#include <span>
int main()
{
constexpr int carray[3] = { 0, 1, 2 };
constexpr std::array<int, 3> array{ 0, 1, 2 };
using S = std::span<const int, 3>;
/*constexpr*/ S span1{ array.data(), 3 };
/*constexpr*/ S span2{array.begin(), array.end()};
/*constexpr*/ S span3{carray};
/*constexpr*/ S span4{array};
}
Run Code Online (Sandbox Code Playgroud)
实际上是否可以创建constexpr span类型,因为似乎构造函数在必须初始化指针或引用时永远无法在编译时求值吗?
这是用SFINAE检测constexpr的后续问题.
我想检测一个元组的元素(或任何可以使用的元素std::get)是否为constexpr.所以我编写了以下助手,类似于Xeo给出的:
template<size_t> struct sfinae_true : std::true_type{};
template<size_t N, class T>
auto check(const T& arg) -> sfinae_true<(std::get<N>(arg),N)>;
template<size_t N, class>
std::false_type check(...);
Run Code Online (Sandbox Code Playgroud)
现在我的测试驱动代码:
int main()
{
constexpr std::tuple<size_t, size_t> arg(4,5);
typedef decltype(check<0,decltype(arg)>(arg)) is_cexpr;
std::cout << "is constexpr? " << is_cexpr::value << '\n';
}
Run Code Online (Sandbox Code Playgroud)
但是,这总是打印出来false给我!要检查由于某种原因并不总是调用错误的重载,我注释掉了错误的重载并得到编译器错误:
注意:候选模板被忽略:替换失败[N = 0,T = const std :: tuple]:非类型模板参数不是常量表达式
自动检查(const T&arg) - > sfinae_true <(std :: get( ARG),0)>;
但是,我知道我可以调用std::get<N>(arg)并获得constexpr值:
template<size_t N>
class A{};
int main()
{
constexpr std::tuple<size_t, size_t> …Run Code Online (Sandbox Code Playgroud)