我想创建一个静态分配2 ^ N字节数组的结构,但我不希望此结构的用户将此大小指定为指数.例:
my_stupid_array<char, 32> a1; // I want this!
my_stupid_array<char, 5> a2; // And not this...
Run Code Online (Sandbox Code Playgroud)
如何检查此模板参数是否为2的幂并警告用户有关于此的好消息?
我已经能够通过一个简单的模板检查这个:
template<int N>
struct is_power_of_two {
enum {val = (N >= 1) & !(N & (N - 1))};
};
Run Code Online (Sandbox Code Playgroud)
但是,我无法通过合理的消息警告用户.有任何想法吗?
编辑
修复了模棱两可的例子.
编辑
1确实是2的幂.修好了!:)
编辑
使用BOOST_STATIC_ASSERT,我收到此代码与GCC的编译错误:
template<int N>
struct is_power_of_two {
enum {val = (N >= 1) & !(N & (N - 1))};
BOOST_STATIC_ASSERT(val);
};
Run Code Online (Sandbox Code Playgroud)
错误
..\main.cpp:29:1: error: invalid application of 'sizeof' to incomplete type 'boost::STATIC_ASSERTION_FAILURE<false>'
Run Code Online (Sandbox Code Playgroud)
编辑 …
我一直在乱搞SVN构建的clang来试验放松的规则constexpr.我之前无法确定的一件事是,是否可以在constexpr函数中在编译时循环遍历元组内的元素.
因为我没有要测试的符合C++ 14的标准库,所以我准备了以下等效测试:
template<int N>
constexpr int foo() {
return N;
}
constexpr int getSum() {
auto sum = 0;
for (auto i = 0; i < 10; ++i) {
sum += foo<i>();
}
return sum;
}
constexpr auto sum = getSum();
Run Code Online (Sandbox Code Playgroud)
这里有趣的部分是foo<i>().在非constexpr函数中,我希望它无法编译,因为您根本无法使用运行时int来生成模板的编译时实例化.constexpr但是,因为这是一个功能,我怀疑这是否可行.特别是,该值在编译时是已知的,即使它允许变异.
我知道以下代码将编译:
constexpr auto nValue = 2;
foo<nValue>();
Run Code Online (Sandbox Code Playgroud)
在SVN clang中,我的第一个例子没有:
test2.cpp:19:12: error: no matching function for call to 'foo'
sum += foo();
^~~~~~
test2.cpp:11:15: note: candidate template ignored: invalid explicitly-specified … 我有一个模板化的类A和一个f返回A对象的模板化函数.我想f<T>成为朋友,现在A<T>仍然是constexpr
template <typename T>
class A;
template <typename T>
constexpr A<T> f();
//f<T> is a friend of A<T>
template <typename T>
class A {
friend /* constexpr? */ A f<T>();
constexpr A() {}
};
template <typename T>
constexpr A<T> f() { return {}; }
int main() {
constexpr auto a = f<void>();
}
Run Code Online (Sandbox Code Playgroud)
我不能让clang和gcc同意这里的内容.如果我没有constexpr输入好友声明,gcc工作正常但clang不会编译它,错误的:
main.cpp:18:18: error: constexpr variable 'a' must be initialized by a constant expression
constexpr …Run Code Online (Sandbox Code Playgroud) 假设您有一个为您的应用程序生成一些安全性令牌的函数,例如一些哈希盐,或者可能是对称或非对称密钥.
现在假设您在C++中将此函数作为constexpr,并根据某些信息(例如,构建号,时间戳,其他内容)为构建生成密钥.
你是一个勤奋的程序员,确保并以适当的方式调用它,以确保它只在编译时被调用,因此死剥离器从最终的可执行文件中删除代码.
但是,您无法确定其他人是否会以不安全的方式调用它,或者编译器可能不会删除该功能,然后您的安全令牌算法将成为公共知识,使其成为公共知识更容易让攻击者猜测未来的令牌.
或者,除了安全性之外,假设该函数需要很长时间才能执行,并且您希望确保它在运行时期间永远不会发生,并且会给最终用户带来糟糕的用户体验.
有没有办法确保在运行时永远不会调用constexpr函数?或者,在运行时抛出一个断言或类似的东西就可以了,但不像编译错误那样明显.
我听说有一些方法涉及抛出一个不存在的异常类型,所以如果constexpr函数没有被删除,你会得到一个链接器错误,但是听说这只适用于某些编译器.
远程相关的问题:强制constexpr在编译时进行评估
我有两个结构a和b:
struct a {
static constexpr int f() {
return 1;
}
static constexpr int c = f();
};
template<int I>
struct b {
static constexpr int f() {
return I;
}
static constexpr int c = f();
};
Run Code Online (Sandbox Code Playgroud)
a显然不起作用,因为f这里没有定义.但为什么地狱b有效呢?
对不起,这将是一个很长的帖子,但我觉得你需要所有的代码来看看发生了什么.
所以,我一直在尝试将编译时字符串转换为数据结构解析器.想象一下像正则表达式这样的东西,其中字符串在编译时被"编译"成数据结构但在运行时执行(只要输入字符串当然是常量).但是我遇到了一个我不太明白错误的问题:
基本上,我的设计是一个2遍解析器:
这是事情的样子:
// a class to wrap string constants
class constexpr_string {
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1) {}
public:
constexpr size_t size() const { return size_; }
constexpr size_t capacity() const { return size(); }
constexpr size_t empty() const { return size() != 0; }
public:
constexpr char operator[](size_t n) const { return string_[n]; }
private:
const char *string_;
size_t size_;
};
// would have loved to …Run Code Online (Sandbox Code Playgroud) 我们的团队正在使用具有10多年历史的C ++代码库,并且最近切换到了C ++ 17编译器。因此,我们正在寻找使代码现代化的方法。在YouTube的一次会议演讲中,我听到了用替换const char*全局字符串的建议constexpr string_view。
由于我们的代码中有很多这样的const char*全局字符串常量,因此我想问一下是否需要了解一些陷阱或潜在问题?
考虑以下代码:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
auto x = f();
return x.substr(1, 3);
}
int foo() { return g().length(); }
Run Code Online (Sandbox Code Playgroud)
如果我用 GCC 10.2 和 flags 编译它--std=c++17 -O1,我会得到:
foo():
mov eax, 3
ret
Run Code Online (Sandbox Code Playgroud)
此外,据我所知,这段代码没有任何未定义的行为问题。
但是 - 如果我添加 flag -fsanitize=undefined,编译结果是:
.LC0:
.string "hello"
foo():
sub rsp, 104
mov QWORD PTR [rsp+80], 5
mov QWORD PTR [rsp+16], 5
mov QWORD PTR [rsp+24], OFFSET FLAT:.LC0
mov QWORD PTR [rsp+8], 3
mov QWORD …Run Code Online (Sandbox Code Playgroud) 所以我读了关于constexpr 和 const 之间有什么区别的有趣答案,但我很好奇 #define 和 constexpr 之间有什么区别?我觉得 constexpr 只是一个可以选择类型的#define。
我可以constexpr在给出定义之前在 C++ 中声明一个函数吗?
考虑一个例子:
constexpr int foo(int);
constexpr int bar() { return foo(42); }
constexpr int foo(int) { return 1; }
static_assert(bar() == 1);
Run Code Online (Sandbox Code Playgroud)
实际上所有编译器都支持,demo:https : //gcc.godbolt.org/z/o4PThejso
但是如果foo在模板中转换函数:
constexpr int foo(auto);
constexpr int bar() { return foo(42); }
constexpr int foo(auto) { return 1; }
static_assert(bar() == 1);
Run Code Online (Sandbox Code Playgroud)
然后 Clang 拒绝接受它,说https://gcc.godbolt.org/z/EG7cG9KTM:
<source>:5:15: error: static_assert expression is not an integral constant expression
static_assert(bar() == 1);
^~~~~~~~~~
<source>:2:30: note: undefined function 'foo<int>' cannot be used …Run Code Online (Sandbox Code Playgroud)