我试图在编译时确定a std::initializer_list中的所有值是否唯一.我找到了一个解决方案,以确定列表的大小,但无法将其应用于内容.我已尝试使用自由函数和构造函数,但这两种方法都导致GCC 4.7.2出现以下错误.
错误:静态断言
错误的非常量条件:'begin'不是常量表达式
我意识到std::initializer_list没有声明成员,constexpr但我希望有一个像尺寸验证的解决方案.是否可以使用以下内容在编译时验证内容?
#include <initializer_list>
template<typename InputIterator>
constexpr bool Validate(InputIterator begin, InputIterator end)
{
static_assert(*begin == *end, "begin and end are the same");
// The actual implemetnation is a single line recursive check.
return true;
}
template<typename InputType>
constexpr bool Validate(const std::initializer_list<InputType>& input)
{
// "-1" removed to simplify and eliminate potential cause of error
return Validate(input.begin(), input.end() /* - 1 */);
}
int main()
{
Validate({1, 2, 1});
}
Run Code Online (Sandbox Code Playgroud) 在使用constexpr中的boost数学常量并建议OP使用boost的模板函数constexpr而不是非模板化常量来平息clang错误后,我决定尝试查看哪些条件会重现clang中的错误.让我们尝试复制boost的宏扩展到:
namespace double_constants{ static const double name = 25; }
static constexpr double SEC3 = double_constants::name;
Run Code Online (Sandbox Code Playgroud)
这给出了以下错误(跟随Coliru)
clang++ -std=c++1y -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp:5:25: error: constexpr variable 'SEC3' must be initialized by a constant expression
static constexpr double SEC3 = double_constants::name;
^ ~~~~~~~~~~~~~~~~~~~~~~
main.cpp:5:32: note: read of non-constexpr variable 'name' is not allowed in a constant expression
static constexpr double SEC3 = double_constants::name;
^
main.cpp:3:49: note: declared here
namespace double_constants{ static …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用哈希函数在C中使用基于字符串的开关表达式。我已经能够使用'constexpr'使它与干净的语法一起使用,并且Clang / LLVM转换为C ++,即使代码是C。
但是,将其作为C ++进行编译当然会有一些奇怪的副作用,例如缺少void *隐式转换会变得很尴尬。
因此,问题是如何解决这个难题(为什么不将C11委员会的掌声压在C规范上)
这是我当前的示例代码:
constexpr uint64 cHash(char const* text, uint64 last_value = basis)
{
return *str ? cHash(text+1, (*text ^ last_value) * prime) : last_value;
}
void SwitchFunction(char const* text)
{
switch(Hash(text))
{
case cHash("first"):
break;
case cHash("second"):
break;
case cHash("third"):
break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud) 尝试使用constexpr属性创建结构的成员而不是静态会导致编译器错误(请参阅下文).这是为什么?对于单个常量值,我将在内存中使用此值,直到程序终止而不仅仅是struct的范围?我应该回去使用宏吗?
struct foo
{
constexpr int n = 10;
// ...
};
error: non-static data member cannot be constexpr; did you intend to make it static?
Run Code Online (Sandbox Code Playgroud) 我认为这是不可能的,但我想在放弃之前问你.
我想要像constexpr增量一样的东西.
#include <iostream>
constexpr int inc() {
static int inc = 0;
return inc++;
}
class Foo {
static const int Type = inc();
};
class Foo2 {
static const int Type = inc();
};
int main() {
std::cout << "Foo1 " << Foo1::Type << st::endl;
std::cout << "Foo2 " << Foo2::Type << st::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想把它称为某些类而不是手动(我使用CRTP),为每个类提供不同的类型,但类型需要是const.无论如何在C++中实现类似的东西?(C++ 17 + TS)
请考虑以下代码:
constexpr auto f()
{
auto str = "Hello World!";
return str;
}
int main(int argc, char* argv[])
{
static constexpr auto str = f();
std::cout << str << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是正常的,我的编译器没有显示任何警告?它是否定义了行为?我能保证程序会显示"Hello World!"吗?我希望"Hello World!"不要超出功能范围......
我想将"数组"转换bool为整数序列.所以我需要std::array在编译时计算一个.
这是我的代码
#include <array>
template<typename InputIt, typename T >
inline constexpr typename std::iterator_traits<InputIt>::difference_type
count( InputIt first, InputIt last, const T &value ) {
typename std::iterator_traits<InputIt>::difference_type ret = 0;
for (; first != last; ++first) {
if (*first == value) {
ret++;
}
}
return ret;
}
template<bool ..._values>
struct keep_value {
static constexpr std::size_t numberOfValues = sizeof...(_values);
static constexpr bool values[] = {_values...};
static constexpr std::size_t numberToKeep = count(values, values + numberOfValues, true);
static constexpr std::array<std::size_t, …Run Code Online (Sandbox Code Playgroud) c++ template-meta-programming variadic-templates constexpr c++14
可以在函数中使用static局部变量吗?constexpr例如:
#include <string_view>
#include <utility>
enum class axis {
x, y, z
};
constexpr std::string_view axis_name(axis a) {
// use static constexpr to avoid putting the table onto the stack
static constexpr std::string_view names[] {
"x", "y", "z"
};
return names[std::to_underlying(a)];
}
constexpr auto x_name = axis_name(axis::x);
Run Code Online (Sandbox Code Playgroud)
GCC 12 无法编译此错误:
<source>:9:39: error: 'names' defined 'static' in 'constexpr' context
9 | static constexpr std::string_view names[] {
| ^~~~~
Run Code Online (Sandbox Code Playgroud)
其他编译器允许它。规则是什么?什么时候允许?
static一般使用,或者static const,或者根据 cppreference.com,std::initializer_lists 具有constexpr 构造函数和constexpr 大小方法(C++14 起)。
尽管我使用的编译器似乎同意 constexpr 初始值设定项列表的大小确实是 constexpr,但在某些情况下,它不相信我的列表是 constexpr。由于 std::initializer_lists 可能涉及一些“编译器魔法”,我开始想知道 constexpr 是否不适用于它们,其方式与适用于非魔法对象的方式完全相同。
我跳到 Compiler Explorer 上,发现主要编译器在这个主题上并不一致。
那么以下四种情况的正确行为(根据标准)是什么?
#include <initializer_list>
using size_type = std::initializer_list<int>::size_type;
template <typename T>
size_type Foo(std::initializer_list<T> const &list) {
return list.size();
}
int main() {
// 1. Example based on
// https://en.cppreference.com/w/cpp/utility/initializer_list/size
// gcc: works
// clang: no viable c'tor or deduction guide
// msvc: works
static_assert(std::initializer_list{1, 2, 3}.size() == 3);
// 2. Make a constexpr std::initializer_list<T> with T …Run Code Online (Sandbox Code Playgroud) 在以下程序中,struct 的默认构造函数A不会初始化其字段v。然后在常量表达式中,std::vector<A>放置有A()对象:
#include <vector>
struct A {
constexpr A() noexcept {}
int v;
};
constexpr bool f() {
std::vector<A> as;
as.reserve(1);
as.emplace_back();
return true;
}
static_assert( f() );
Run Code Online (Sandbox Code Playgroud)
MSVC 编译器抱怨读取未初始化的变量:
<source>(14): error C2131: expression did not evaluate to a constant
<source>(11): note: failure was caused by a read of an uninitialized symbol
<source>(11): note: see usage of 'A::v'
Run Code Online (Sandbox Code Playgroud)
但 GCC 和 Clang 都对该程序很满意。在线演示: https: //godbolt.org/z/addx11aTT
这里哪个编译器是正确的?