假设我想在编译时构建一个图,使用一些算法,然后计算出图中有多少个节点。这似乎是一个理想的情况,而不是模板元编程,因为目标是一个计算产生一个值,而不是真正的类型。我有一些可以工作的代码,但是这个特性太新了,恐怕编译器很宽容,我可以把标准的一部分解释为我不能这么做。
#include <iostream>
struct A { int x; constexpr A(int i) noexcept : x{i} {} };
struct B { A& a; constexpr B(A& a) noexcept : a{a} {} };
constexpr int foo() {
A a{55};
B b{a};
return b.a.x;
}
template<int N>
void output()
{
std::cout << N << std::endl;
}
int main() {
// to be absolutely sure compile time eval'd,
// pass as template arg
constexpr auto b = foo();
output<b>();
}a和b实例都是在编译时创建的,它们具有相同的生存期,因此这应该是“安全的”。但是a是一个非静态对象,这部分标准似乎表示不允许这样做:
如果实体是具有静态存储持续时间的对象,该对象不是临时对象,或者是值满足上述约束的临时对象,或者是函数,则实体是常量表达式的允许结果。
我能不能?GCC和clang都对此没意见。
发布于 2015-07-31 06:11:51
简而言之,您不能在编译时将非静态/临时值作为引用传递。可以将静态/全局值作为constexpr引用传递。但是,在编译时,其他任何东西都是不可用的。
constexpr void foo() {
int a; // run-time value.
...
}一个明显的解决办法是通过价值传递。它是在编译时发生的,所以您可能无法得到通常的优化,但它也发生在编译时。
http://ideone.com/J7mVj5
#include <iostream>
struct A { int x; constexpr A(int i) noexcept : x{i} {} };
struct B { A a; constexpr B(A a) noexcept : a{a} {} };
constexpr int foo() {
B b{55};
return b.a.x;
}
template<int N>
void output()
{
std::cout << N << std::endl;
}
int main() {
// to be absolutely sure compile time eval'd,
// pass as template arg
constexpr auto b = foo();
output<b>();
}另见http://ideone.com/tw4jzG
https://stackoverflow.com/questions/31735037
复制相似问题