我有一个模板基类,期望子类将自身作为模板参数传递。
看起来有点像这样:
template<typename T>
struct Base {
constexpr Base(int x) : m_x(x) {}
private:
int m_x;
};
struct Derived : public Base<Derived>
{
static const Derived LIFE;
constexpr Derived(int x) : Base(x) {}
};
const Derived Derived::LIFE = Derived(42);
Run Code Online (Sandbox Code Playgroud)
编译并按预期工作。但是现在我想将Derived :: LIFE设为constexpr。这有可能吗?
我不能只将它的const限定符更改为constexpr,因为constexpr需要在其声明中进行初始化:
test.cpp:10:28: error: constexpr static data member ‘LIFE’ must have an initializer
static constexpr Derived LIFE;
Run Code Online (Sandbox Code Playgroud)
由于Derived是不完整的类型,因此无法在其中初始化:
test.cpp:10:45: error: invalid use of incomplete type ‘struct Derived’
static constexpr Derived LIFE = Derived(42);
Run Code Online (Sandbox Code Playgroud)
我知道,如果Derived是完整类型,则此问题将消失,但是由于与该问题无关的原因,在这种特殊情况下,我非常喜欢使用自引用模板化基类。
如果我正确地理解了此答案的最后一段,听起来似乎至少有一些讨论会在将来的某个时候更改不完整类型的处理方式,但是现在对我无济于事。
有人知道我上面的代码中有一些技巧可以推迟LIFE的初始化吗?
#include <iostream>
using namespace std;
template<typename T> void print(T&& mX)
{
std::cout << std::forward<T>(mX) << std::endl;
}
struct SomeStruct
{
static constexpr const char* someString{"hello!"};
SomeStruct()
{
print(someString);
}
};
int main()
{
SomeStruct s{};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
clang++ -std=c++1y ./code.cpp -o code.o
/tmp/code-a049fe.o:在函数“ SomeStruct :: SomeStruct()”中:./code.cpp:(.text._ZN10SomeStructC2Ev[_ZN10SomeStructC2Ev]+0xa):未定义对“ SomeStruct :: someString”的引用:错误:链接器命令失败,退出代码为1(使用-v查看调用)
g++ -std=c++1y ./code.cpp -o code.o
/tmp/ccyrTsjS.o:在函数“ SomeStruct :: SomeStruct()”中:code.cpp :(。text._ZN10SomeStructC2Ev [_ZN10SomeStructC5Ev] + 0xd):未定义对“ SomeStruct :: someString”的引用collect2:错误:trud退出状态
为什么发生此链接器错误?难道someString在编译时就无法解决吗?
另外,如果print(someString)将其替换为错误,则不会发生cout << someString;
我需要知道在指定noexcept说明符时是否定义了NDEBUG.我正在考虑这个constexpr功能:
constexpr inline bool is_defined() noexcept
{
return false;
}
constexpr inline bool is_defined(int) noexcept
{
return true;
}
Run Code Online (Sandbox Code Playgroud)
然后使用它像:
void f() noexcept(is_defined(NDEBUG))
{
// blah, blah
}
Run Code Online (Sandbox Code Playgroud)
标准库或语言是否已经为此提供了便利,以便我不会重新发明轮子?
#include <utility>
struct A {
constexpr auto one(int a) {
return std::integral_constant<int, _data[a]>{};
}
constexpr int two(int a) const {
return _data[a];
}
int _data[10];
};
int main() {
constexpr auto ex = A{{1,2,3,4,5,6,7,8,9,10}};
std::integral_constant<int, ex.two(3)> b{};
}
Run Code Online (Sandbox Code Playgroud)
上面的代码不会在trunk Clang中编译.错误在one()成员函数中,并说:
cc.cpp:57:44: note: implicit use of 'this' pointer is only allowed
within the evaluation of a call to a 'constexpr' member function.
Run Code Online (Sandbox Code Playgroud)
显然,功能标记constexpr,如果你注释掉one()成员,一切编译罚款,所以我们显然能够创建integral_constant从ex从,但不直接struct?看来,当我需要auto返回类型演绎时,它失败并声称功能不是constexpr?
这是预期的吗?我觉得这应该不是问题,如果这是预期的行为,我会感到惊讶.
这个
int main()
{
std::cout << range(1, 11).reverse().sort().sum() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
就是所有内容main,正如代码所说,它创建了一个从1到10(包括1和10)的列表,将其反转,通过排序取消反转,并计算总和.因此输出应为55.
代码是一个实验,(ab)使用constexprC++ 14中的宽松要求.我尽力创建一个编译时列表类,但实际上还远远不够.这个类是不完整的,但它仍然可以模仿很多功能风格的编程.
据我所知,需要constexpr让编译器在编译时评估一些东西.所以我认为编译器可以简单地用代码55替换所有代码,但事实并非如此.代码确实具有在编译时获得结果所需的一切.我错过了什么?
从评论中,我试图通过使用结果来检查问题static_assert.clang和gcc都给了我一个错误,但我也没理解,而后者似乎被打破了......
铛
a.cpp:142:17: error: static_assert expression is not an integral constant expression
static_assert(range(1, 11).reverse().sort().sum() == 55, "");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.cpp:60:23: note: assignment to object outside its lifetime is not allowed in a constant
expression
l.array[l.length++] = t;
^
a.cpp:134:9: note: in call to '&l->add(1)'
l = l.add(a);
^
a.cpp:142:17: note: in call to 'range(1, 11, 1)'
static_assert(range(1, 11).reverse().sort().sum() …Run Code Online (Sandbox Code Playgroud) #include <iostream>
using namespace std;
constexpr int f(bool b){ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // Ill-Formed, No Diagnostic Required
int main(){
try{
f();
}catch( int x ){
cout << "x = " << x << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该代码是C ++ 14标准(ISO / IEC 14882:2014)第7.1.5节第5段的示例:
对于非模板,非默认constexpr函数或非模板,非默认,非继承constexpr构造函数,如果不存在参数值,则该函数或构造函数的调用可以是核心常量的评估子表达式表达式(5.19),程序格式错误;无需诊断。
它被描述为“ 格式错误,不需要诊断 ”,因为throw-expression不是核心常量表达式(5.19 / 2)。但是,Clang和GCC都可以成功编译它(Ideone)。
我还发现了有关标准措辞的这些有趣的讨论:
一个/该程序是否可能“ 格式错误,不需要诊断 ”,并且允许编译器成功编译该程序?
我在static constexpr属性方面遇到了一些困难:它与enum class成员类型的整数类型一起使用,但是当我尝试使用静态初始化的整数数组时,它会在链接说出undefined reference to S::a内部时失败main.
这是clang 3.9或g ++ 6.3和ld 2.27.90; 以及所有这一切-std=c++14.
以下是重现此内容的最快速片段:
struct S
{
static constexpr int a[5] = {0};
};
int main()
{
S s{};
[[gnu::unused]] int b = s.a[0]; // force S stuff to be emitted
return 0;
}
Run Code Online (Sandbox Code Playgroud)
感谢您对此情况的任何建议.
如这个问题所示:link,如果两个if分支都有效,则两者之间没有区别:
const int foo = 5;
if (foo == 5)
{
...
}
else
{
...
}
Run Code Online (Sandbox Code Playgroud)
和
const int foo = 5;
if constexpr (foo == 5)
{
...
}
else
{
...
}
Run Code Online (Sandbox Code Playgroud)
在优化方面(在两种情况下else都不会实例化分支)。因此,如果if可以在编译时检查vanilla中的表达式(它涉及到const或constexpr),那么优化也可以在此处进行。
我以前认为这是的目的if constexpr,但我错了。那么,除了用例之外,还有没有if constexpr其他用例,那么我们可能只有许多if分支有效之一?
我试图得到一个unsigned完全用1填充的(二进制表示形式是32个。我尝试使用以下方法:
constexpr unsigned all_ones = (((1 << 31) - 1) << 1) | 1;
Run Code Online (Sandbox Code Playgroud)
但是在编译时(在Ubuntu上为g ++),会出现以下错误:
error: overflow in constant expression [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
是什么导致此错误?在我看来,此表达式看起来不错,如下所示:
1 = 000...001
<< 31 = 100...000
- 1 = 011...111
<< 1 = 111...110
| 1 = 111...111
Run Code Online (Sandbox Code Playgroud)
我知道我可以通过其他方式(例如〜0u)获得所需的值,但是我要问的是为什么这种方法不起作用。
我想使用数学函数在编译时填充constexpr std :: array。有可能以简单的方式吗?
我找到了以下解决方案:C ++ 11:数组的编译时间计算。但是,还有其他仅使用std的现代解决方案吗?这似乎让我感到困惑。
int main()
{
// This is the array I need to fill
constexpr std::array<double, 100000> elements;
for (int i=0; i!=100000; ++i)
{
// Each element is calculated using its position with long exponential maths.
elements[i] = complexFormula(i); // complexFormula is constexpr
}
double anyVal = elements[43621];
// ...
}
Run Code Online (Sandbox Code Playgroud) constexpr ×10
c++ ×9
c++14 ×6
c++11 ×3
linker ×2
arrays ×1
auto ×1
bitmask ×1
compile-time ×1
fill ×1
if-constexpr ×1
optimization ×1
templates ×1
throw ×1