struct X {
constexpr static char a1[] = "hello"; // Okay
constexpr static const char* a2[] = {"hello"}; // Error
};
int main(){}
Run Code Online (Sandbox Code Playgroud)
使用gcc编译会出错:
错误:在'{'标记之前,不允许使用括号括起的初始值设定项
这是constexpr的非法使用吗?
编辑
我尝试了3个不同版本的gcc,它在我最新的4.7.0上编译(我刚刚下载它,我使用的是mingw-w64),所以它看起来是一个固定的bug(这个bug的链接会是不过很好!)
4.7.0 20120311(预发行)//好的
4.6.4 20120305(预发布)//错误
4.7.0 20110829(实验性)//错误
我为LPC1114编译,这是一个小型ARM(实际上是Cortex)目标.RAM比ROM更受限制.我使用最新的Mentor(CodeBenchLite)GCC编译器(GCC 4.6.3).我有一些我希望在ROM中拥有的常量对象.据我所知,下面代码中的ffx对象最终应该在ROM(代码)中,但它放在DATA中.
class flop {
public:
int x;
constexpr flop( int x ) : x(x){}
};
extern constexpr flop ffx( 1 );
Run Code Online (Sandbox Code Playgroud)
如何说服编译器预先计算对象并将其放在ROM中?
或者我应该问:
=======================================
这个bugzilla条目c ++/49673似乎表明我的已知问题,可能已在GCC 4.7中修复.不幸的是,我更喜欢使用内置的Mentor/CodeSourcery,它仍然是4.6.3.所以我想暂时我会遇到这个bug.:(
我正在寻找静态大小的std::valarray实现。
我自己可以轻松实现它,但是我需要进行constexpr操作(求和,减法等),而且这样做很无聊/容易出错,所以我在这里问是否有一个流行的实现。
如果我必须自己实现这一点,那么您认为在这种情况下表达式模板值得吗?
我刚刚尝试使用clang 3.3和Ubuntu 13.04上的GCC 4.7.3标准库头文件编译相当大的代码.除了一个问题外,一切顺利.这段代码已经在这台机器上编译了标准的Ubuntu clang 3.2软件包,所以我假设这是clang 3.3编译器的一些变化.与使用复杂标头的const和constexpr相关的问题.特别是复杂类型具有以下代码块
#ifdef __GXX_EXPERIMENTAL_CXX0X__
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 387. std::complex over-encapsulated.
constexpr double
real() { return __real__ _M_value; }
constexpr double
imag() { return __imag__ _M_value; }
#else
double&
real() { return __real__ _M_value; }
const double&
real() const { return __real__ _M_value; }
double&
imag() { return __imag__ _M_value; }
const double&
imag() const { return __imag__ _M_value; }
#endif
Run Code Online (Sandbox Code Playgroud)
在我的编译中,我输入第一个代码块,因此编译器可以看到
constexpr double real() { return __real__ _M_value; }
Run Code Online (Sandbox Code Playgroud)
这导致clang产生错误,实际成员函数不是const,具有以下内容
/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/complex:1212:7:
note: candidate function …Run Code Online (Sandbox Code Playgroud) 我想创建一个我可以用作模板参数的字符串文字.它将编译器抛入某种无限循环.有什么问题并修复?
template <char...> struct slit { };
template <typename ...A>
constexpr auto make_slit(char const* const s, A const ...args)
{
return *s ? make_slit(s + 1, *s, args...) : slit<args...>();
}
int main()
{
auto const tmp_(make_slit("slit"));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
强制性错误(带clang++ -std=c++1y):
t.cpp:4:16: fatal error: recursive template instantiation exceeded maximum depth of 256
constexpr auto make_slit(char const* const s, A const ...args)
^
t.cpp:6:15: note: in instantiation of function template specialization 'make_slit<char, char, char, char, char, char, char, …Run Code Online (Sandbox Code Playgroud) 能够将传递给文字运算符的字符串转换为MPL序列将非常有用,因为我们可以根据字符串的内容控制代码生成.以前,我认为这是不可能的,因为constexpr函数的参数不被视为函数体内的常量表达式.但是,我提出了在Clang 3.4.2和GCC 4.8.2下编译的以下解决方法:
#include <cstdint>
#include <iostream>
#include <typeinfo>
struct string
{
const uintmax_t m_str[64];
const size_t m_length;
template <class... Ts>
constexpr string(const Ts... ts) :
m_str{(uintmax_t)ts...}, m_length{sizeof...(Ts)} {}
constexpr size_t size() const { return m_length; }
constexpr size_t length() const { return m_length; }
constexpr uintmax_t operator[](size_t n) const { return m_str[n]; }
};
template <uintmax_t... Ts> struct sequence {};
constexpr auto
operator"" _tag(const char* str, size_t n)
{
return n == 0 ? string{} :
n == 1 …Run Code Online (Sandbox Code Playgroud) c++ template-meta-programming user-defined-literals constexpr c++14
让我们直接看一下简化的代码(编译:GCC 6.3.0)
#include<iostream>
#include<cstring>
using namespace std;
int main(int arga, char* argv[]) {
const char cs[] = "Hello";//define a constant c-style string
constexpr size_t newSize = strlen(cs) + strlen(" ");//Error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器产生错误: strlen(((const char*)(&cs)))不是常量表达式
但是,当我将c字符串定义移动到全局范围时,问题就会消失.
....
const char cs[] = "Hello";
int main(int arga, char* argv[]) {
constexpr size_t newSize = strlen(cs) + strlen(" ")//No Error
....
}
Run Code Online (Sandbox Code Playgroud)
有人能解释发生了什么吗?为什么strlen()将全局定义的常量c-string视为常量表达式,而不是堆栈中的那个?
我有以下代码,我厌倦了编译器无法看到作为函数的参数传递的变量是constexpr的事实,所以我必须使用arity 0函数而不是1参数函数.
我知道这不是编译器错误,但我想知道是否有成语可以解决这个问题.
#include <array>
#include <iostream>
static constexpr std::array<int, 5> arr{11, 22, 33, 44, 55};
template <typename C, typename P, typename Y>
static constexpr void copy_if(const C& rng, P p, Y yi3ld) {
for (const auto& elem: rng) {
if (p(elem)){
yi3ld(elem);
}
}
}
// template<std::size_t N>
static constexpr auto get_evens(/* const std::array<int, N>& arr */) {
constexpr auto is_even = [](const int i) constexpr {return i % 2 == 0;};
constexpr int cnt = [/* &arr, */&is_even]() …Run Code Online (Sandbox Code Playgroud) (扰流器 -这是一个自我回答的问题)让我们假设我有两个索引序列,例如using i1 = std::index_sequence<1, 3, 5, 7>;和using i2 = std::index_sequence<2, 4, 6, 8>;
我想创建一个数组(在编译时),该数组中将依次包含8个元素:1, 2, 3, 4, 5, 6, 7, 8,以便以下代码可以工作(例如,在全局范围内):
std::array<int, 8> arr = make_array(i1{}, i2{});
Run Code Online (Sandbox Code Playgroud)
注意:如果我只想要一个序列,则解决方案很简单:
template<size_t... Ix>
constexpr auto make_arr(std::index_sequence<Ix...> )
return std::array{Ix...};
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我需要连接两个序列,那并不是那么简单,例如,这是行不通的:
template<size_t... Ix1, size_t... Ix2>
constexpr auto make_arr(std::index_sequence<Ix1...>, std::index_sequence<Ix2...>)
return std::array{(Ix1, Ix2)...};
}
Run Code Online (Sandbox Code Playgroud)
(上面的代码将使用第二个序列中的值填充数组)。
另一个可能的解决方案是使用constexpr函数,该函数首先定义一个具有默认值的数组,然后将索引序列中的值复制到该数组中,但是虽然该方法适用于ints,但不适用于某些更为复杂的类型,这些类型不是默认的-可构造的(显然,它们不是索引序列的一部分,但可以是其他东西)。
是否有不需要循环和默认构造值的解决方案?任何可用的C ++标准都是公平的游戏。
c++ template-meta-programming variadic-templates constexpr c++17
正确吗
constexpr int* p = nullptr;
Run Code Online (Sandbox Code Playgroud)
声明constexpr指针(而不是constexpr int指针)?
这个定义
int* constexpr p = nullptr;
Run Code Online (Sandbox Code Playgroud)
给出编译错误。