我在使用常量初始化类时遇到了麻烦:
为什么使用指向同一类中成员的指针初始化会导致错误?出现错误而不使用"使用"类!
class A
{
private:
int a;
const int* const aptr;
public:
constexpr A( int _a):
a(_a)
, aptr( &a) // why aptr could not be initialized?
{}
};
class Data { } d1;
class B
{
private:
Data* dptr1;
public:
constexpr B(Data* _p): dptr1( _p) {}
};
class Use
{
static constexpr A a{2}; // fail! error: field initializer is not constant
static constexpr B b{&d1}; // works
};
Run Code Online (Sandbox Code Playgroud) 我有一个类模板,它基于模板参数构建一个简单的数组作为其成员之一.我需要能够将数组中的每个元素初始化为其中一个构造函数中的单个值.不幸的是这个构造函数必须是constexpr.
相关部分归结为:
template <typename T, size_t N>
class foo
{
T data[N];
constexpr foo(T val)
{
// initialize data with N copies of val
}
};
Run Code Online (Sandbox Code Playgroud)
使用std::fill或循环与constexpr要求不兼容.初始化: data{val}仅设置数组的第一个元素,并对剩余部分进行零初始化.
怎么能实现这一目标?
我觉得应该有一个可变参数模板和元组等的解决方案......
我想创建一个模板类,其成员是一个constexpr数组.当然,数组需要根据其类型进行不同的初始化,但我不能在不初始化的情况下声明数组.问题是我在模板专业化之前不知道数组的值.
//A.hpp
template<typename T>
class A {
public:
static constexpr T a[];
constexpr A() {};
~A() {};
}
//B.hpp
class B: public A<int> {
public:
constexpr B();
~B();
};
//B.cpp
template<>
constexpr int A<int>::a[]={1,2,3,4,5};
B::B() {}
B::~B() {}
Run Code Online (Sandbox Code Playgroud)
如何正确初始化B中的A :: a []?
std::array从生成器函数编写一个简单的编译时工厂,我偶然发现:clang ++ 3.5.1和g ++ 4.9.2不同意函数是否constexpr存在.
代码(这是c ++ 14!):
#include <array>
#include <utility>
template <class T, std::size_t N, class GenType, std::size_t... I>
constexpr std::array<T, N>
make_array_impl (GenType gen, std::index_sequence <I...>)
{
return {{ gen (I)... }};
}
template <class T, std::size_t N, class GenType>
constexpr std::array<T, N>
make_array (GenType gen)
{
return make_array_impl <T, N> (
gen,
std::make_index_sequence <N> {}
);
}
constexpr int
generator_const (std::size_t /* index */)
{
return 1;
}
constexpr auto
a = make_array …Run Code Online (Sandbox Code Playgroud) 这与如何通过内联函数强制const传播有关?Clang有一个集成的汇编程序; 它不使用系统的汇编程序(通常是GNU AS(GAS)).Non-Clang提前完成了数学运算,一切都"正常".
我说"早",因为@nm反对将其描述为"由预处理器执行的数学".但是这个想法是在编译时知道值,并且应该提前评估它,就像预处理器评估a时一样#if (X % 32 == 0).
下面,Clang 3.6抱怨违反约束.看起来这个常数并没有在整个过程中传播:
$ export CXX=/usr/local/bin/clang++
$ $CXX --version
clang version 3.6.0 (tags/RELEASE_360/final)
Target: x86_64-apple-darwin12.6.0
...
$ make
/usr/local/bin/clang++ -DNDEBUG -g2 -O3 -Wall -fPIC -arch i386 -arch x86_64 -pipe -Wno-tautological-compare -c integer.cpp
In file included from integer.cpp:8:
In file included from ./integer.h:7:
In file included from ./secblock.h:7:
./misc.h:941:44: error: constraint 'I' expects an integer constant expression
__asm__ ("rolb %1, %0" : "+mq" (x) : "I" ((unsigned …Run Code Online (Sandbox Code Playgroud) 考虑结构:
struct mystruct { };
Run Code Online (Sandbox Code Playgroud)
这总是有效的:
constexpr mystruct mystructInstance = mystruct();
Run Code Online (Sandbox Code Playgroud)
即POD的值初始化是constexpr?类似地,如果结构被定义为:
struct mystruct { ~mystruct(); };
Run Code Online (Sandbox Code Playgroud)
最后,这个怎么样:
struct mystruct { mystruct(); ~mystruct(); };
Run Code Online (Sandbox Code Playgroud)
我没有宣布ctr为constexpr,但有没有任何隐含的扣除规则可以保证这一点吗?
我的模板结构的静态constexpr成员遇到了一些问题.代码编译但我得到链接错误.这是我正在尝试做的事情:
template<int n>
struct Test {
static constexpr auto invoke = make_tuple(2, "test", 3.4);
};
template<typename T>
void test(T&& t) {
cout << t << endl;
}
int main() {
test(get<0>(Test<2>::invoke));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我有链接错误,所以我尝试了这个:
template<int n>
struct Test {
static constexpr auto invoke = make_tuple(2, "test", 3.4);
};
// declare it outside the class
template<int n>
constexpr decltype(Test<n>::invoke) Test<n>::invoke;
template<typename T>
void test(T&& t) {
cout << t << endl;
}
int main() {
test(get<0>(Test<2>::invoke));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但相反,我得到了这个奇怪的错误: …
示例代码test.cpp
#include <array>
#include <string>
int main ()
{
// OK
const std::array<int, 2> array_int = {42, 1337};
std::array<float, array_int.size()> array_float_ok;
// Error
const std::array<std::string, 2> array_string = {"foo", "bar"};
std::array<float, array_string.size()> array_float_error;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用g ++ 4.8.4编译(Ubuntu 14.04)
g++ -Wall -std=c++0x test.cpp -o test
Run Code Online (Sandbox Code Playgroud)
给出以下错误消息
test.cpp: In function ‘int main()’:
test.cpp:14:39: error: call to non-constexpr function ‘constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::basic_string<char>; long unsigned int _Nm = 2ul; std::array<_Tp, _Nm>::size_type = long unsigned int]’ …Run Code Online (Sandbox Code Playgroud) 如果初始化语法和'constexpr if'中有以下内容,我找不到有关新C++ 17的任何信息:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0128r1.html
然而,Clang-HEAD支持语法...
constexpr auto f() { return true; }
int main() {
if constexpr(constexpr auto x = f(); x) { }
}
Run Code Online (Sandbox Code Playgroud)
在线代码 - > http://melpon.org/wandbox/permlink/dj3a9ChvjhlNc8nr
是否constexpr if有标准保证的初始化程序,因为constexpr if它只是一个" if有constexpr"或者它不能保证并且必须明确地添加到标准中?
请使用以下代码:
#include <array>
constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
Run Code Online (Sandbox Code Playgroud)
随着-std=c++17GCC的完美编译,但Clang抱怨表达式不是一个完整的常量表达式.看起来问题是关于std::next哪个应该是constexpr在C++ 17中.
然而,std::next在std库中,而不是在编译器本身,因此有一些奇怪的事情发生.只是为了让事情变得更好,如果你传给-stdlib=libc++Clang ,那么这个例子就完美地编译了.
到底是怎么回事?谁错了,谁是对的?
编辑
这个问题似乎与使用Godbolt内部的GCC 7.2 工具链相关.如果将--gcc-toolchain=/opt/compiler-explorer/gcc-snapshot参数添加到命令行,一切都可以正常运行.(感谢@einpoklum向godbolt报告了这个问题 - 我速度慢了;))
编辑
对于那些认为旧编译器应该适用于实际标准的人来说,遗憾的是,这种考虑是没有意义的.我在谈论GCC和Clang的最新版本.并且这个问题可以通过两者的主干版本重现.较旧的编译器与此问题无关(相反,MSVC行为会很有趣).