C++标准(github.com/cplusplus/draft)具有time_t转换函数(std::chrono::system_clock::to_time_t和std::chrono::system_clock::from_time_t)对列为static和noexcept但不是constexpr.
由于基本上所有的操作对time_point与duration被constexpr(包括duration_cast和time_point_cast),我想不出任何理由将它们排除在外.快速检查本地计算机上的libstdc ++源代码确认这些函数是作为简单的duration/time_point强制转换实现的.
这两个功能不应该是什么原因constexpr吗?这只是"因为没有人提出他们应该"的情况吗?
我用constexpr复制构造函数编写了一个类.(这是一个结构,使其更简单.)其中一个字段是一个数组.我也要复制它.
struct Foo
{
static constexpr int SIZE = 4;
constexpr Foo() = default;
constexpr Foo(const Foo &foo) :
arr{foo.arr[0], foo.arr[1], foo.arr[2], foo.arr[3]},
bar(foo.bar+1) {}
int arr[SIZE] = {0, 0, 0, 0};
int bar = 0;
};
Run Code Online (Sandbox Code Playgroud)
我的版本有效,但不可扩展.如果我改变SIZE,我必须修改构造函数.另外,代码看起来很难看.
是否有更好的方法在构造函数中复制数组?构造函数必须是constexpr.
请考虑以下代码:
template <typename T, typename P, T P:: *s> struct H {};
struct AA { int i; };
int main()
{
typedef int AA::*PI;
constexpr PI pi = &AA::i;
H<int, AA, &AA::i> h1; // OK
// H<int, AA, pi> h2; // compile error
}
Run Code Online (Sandbox Code Playgroud)
我有成员指针pi指向AA::i.
pi是一个constexpr变量.为什么我不能将它用作模板参数,即使&AA::i直接使用也可以?
我想出了这堂课:
class Point
{
public:
int X, Y;
mutable int Z;
constexpr Point(int x, int y) :X (x), Y(y), Z(0)
{ }
constexpr int GetX() const
{
// Z++; // Wont compile, but following expression is valid!
return X+Z;
}
int GetY() const
{
Z++;
return Y;
}
void FoolConst() const
{
Z++;
}
};
Run Code Online (Sandbox Code Playgroud)
这是用法:
template<int S>
void foo()
{
std::cout << S << std::endl;
}
int main()
{
constexpr Point pt(10, 20);
pt.FoolConst();
char arr[pt.GetX()]; // Both compile, …Run Code Online (Sandbox Code Playgroud) 我正在实现一些非常类似std::vector但在堆栈上使用数组而不是内存分配的东西.
d-tor调用使用SFINAE的函数.
value_type是POD功能有空体.value_type是正常类std::string,则函数有一个正文并正确销毁所有数据.现在,我希望能够使用这个新std::vector的constexpr.然而,即使c-tor被声明constexpr,代码也不会编译,因为类有非平凡的d-tor.
这是代码的一小部分:
template<typename T, std::size_t SIZE>
class SmallVector{
constexpr SmallVector() = default;
~SmallVector(){
destructAll_<value_type>();
}
// ...
template<typename X>
typename std::enable_if<std::is_trivially_destructible<X>::value == true>::type
destructAll_() noexcept{
}
};
Run Code Online (Sandbox Code Playgroud)
constexpr如果value_type是POD并保持非POD数据类型的功能,我可以做什么来使类成为可能.
(当然不是在同一时间)
我们有constexpr自C++ 11以来的功能,并且由于每个新标准(14,1z),它们受到的限制越来越少.
然而,STL中最明显的功能constexpr,即cmath/ math.hfunctions,constexpr在任何标准库实现AFAIK中仍然没有版本.
这只是在C++标准的积压中,还是还有其他原因导致我们仍然没有constexpr这些功能的版本?
请考虑以下代码:
#include <iostream>
template<class T>
struct foo {};
template<>
struct foo<int> {
static constexpr char value[] = "abcde";
};
template<class T>
struct bar {
static constexpr char value[] = "abcde";
};
template<class T>
struct baz {
static constexpr int value = 12345;
};
int main() {
char c = foo<int>::value[2];
char d = bar<int>::value[2];
int e = baz<int>::value;
std::cout << c << d << e << "\n";
}
Run Code Online (Sandbox Code Playgroud)
使用:编译时clang++ -std=c++14 ./test_foo.cc,我得到未定义符号的链接器错误:bar<int>::value和foo<int>::value.当我改为时clang++ -std=c++17,只有一个未定义的符号: …
我正在使用与Xcode 9.3捆绑在一起的clang,我试图了解以下结果是否是C++ 17更改的有意部分:
#include <iostream>
template<typename T> struct Test {
static const int TEN;
};
template<typename T> constexpr int Test<T>::TEN = 10;
int main(int argc, const char * argv[]) {
std::cout << Test<int>::TEN << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用c ++ 11或c ++ 14编译时,会打印"10".但是,用c ++ 17编译它会打印"0".
这是怎么回事?
从en.cppreference.com/w/cpp/language/initialization:
无序动态初始化,其[原文如此]仅适用于(静态/线程局部)类模板静态数据成员和可变模板(因为C ++ 14)未明确专业。
因此,静态模板似乎更容易受到“静态初始化顺序惨败”(TSIOF)的更差版本的攻击(即在翻译单元中无序)。
使用constexpr可以消除此漏洞吗?
即下面的代码的输出保证是success吗?
显然,由于这个问题的性质,实际的例子不足以作为答案。需要引用标准中的报价。(首选C ++ 17答案)
#include<cassert>
template<class T> static constexpr T a = 41;
template<class T> static constexpr T b = a<T>+1;
int main(){
assert(b<int> == 42);
std::cout <<"success\n";
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果有人是专家对这个我有一个相关的,悬而未决的问题(这将是容易对这样的专家来回答)这里。此外,如果我对其他问题的回答是否定的(即constexpr对所有翻译单位都无济于事),这里的含义是什么?
更新:我需要澄清我的关注在这里。原始问题标题询问constexpr模板变量是否要考虑初始化顺序。我已经澄清了。我不担心示例中是否发生了动态初始化。不是。我担心的是,由于不能在动态初始化情况下假设有序初始化,因此可以在常量初始化情况下假设吗?在看到动态初始化的模板变量(在同一翻译单元内)的行为之前,我什至从未想到过这一点。但是,由于动态初始化的静态持续时间模板变量不提供有序的初始化,所以我现在没有理由假设常量初始化的静态持续时间的模板变量也保证了有序的初始化。
同样,我认为没有理由假定编译器中的常量初始化器不需要动态初始化器就可以初始化。在标准中没有警告说没有恒定的初始化是不够的。
我意识到有些人可能认为这是个过分关注的问题,但是我正在开发对安全至关重要的软件,并且在解决此问题之前,我公司已暂停采用C ++ 14。
c++ initialization global-variables language-lawyer constexpr
请考虑以下示例代码:
#include <tuple>
void blah();
int buh;
constexpr auto get()
{
return std::get<0>(std::make_tuple(&blah, &buh));
}
int main()
{
get();
}
Run Code Online (Sandbox Code Playgroud)
人们可以预期,由于函数get()是一个常量表达式,它将返回一个常量.
这不是发生的事情:std::make_tuple,std::get实例化并调用:https://godbolt.org/g/PkHrTp
现在,如果我们替换get()by 的实现
constexpr auto get()
{
constexpr auto x = std::get<0>(std::make_tuple(&blah, &buh));
return x;
}
Run Code Online (Sandbox Code Playgroud)
我们得到了预期的行为:该参数x的计算是优化掉了,甚至在-O0,并且make_tuple,get没有实例化,它可以是相当有用的,以减少二进制膨胀.
是否有一种惯用的方式来强制表单的功能constexpr auto foo()总是像第二个例子中那样?
现在我会诉诸:
#define constexpr_return(X) do { constexpr auto constexpr_return_x_ = X; return constexpr_return_x_; } while(0)
constexpr_return(std::get<0>(std::make_tuple(&blah, &buh)));
Run Code Online (Sandbox Code Playgroud)
例如,但我不知道这是否是最佳的.