【发布时间】:2015-10-21 06:43:57
【问题描述】:
假设我有一个可以通过constexpr 函数返回常量表达式的类:
template<int N>
struct Foo {
constexpr int Bar() const { return N; }
};
如果我想从Foo::Bar() 初始化constexpr 值,我应该如何传递Foo 类型的参数?我已经尝试了这两个,每个内部都有一个示例 constexpr 变量来测试它是否可以初始化:
template<int N>
constexpr int ByValue(Foo<N> f) {
constexpr int i = f.Bar();
return f.Bar();
}
template<int N>
constexpr int ByReference(const Foo<N> &f) {
constexpr int i = f.Bar();
return f.Bar();
}
constexpr int a = ByValue(Foo<1>{});
constexpr int b = ByReference(Foo<1>{});
但是 clang 3.7 会在 ByReference 上引发错误,而 gcc >=5.1 不会:Live demo
main.cpp:15:25: error: constexpr variable 'i' must be initialized by a constant expression
constexpr int i = f.Bar();
^~~~~~~
main.cpp:22:25: note: in instantiation of function template specialization 'ByReference<1>' requested here
constexpr int b = ByReference(Foo<1>{});
当Bar 是constexpr 并返回有效的常量表达式时,采用const Foo & 或普通Foo 有什么区别?
GCC 还是 Clang,哪个是正确的,为什么?如果可以,请参考该标准。
【问题讨论】:
-
在标准的枚举中有一些关于引用的愚蠢语言可以为您提供编译时常量表达式。显然,clang 学究式地尊重该语言,而 g++ 更实际地忽略了它。希望它会得到修复,但我不记得看到任何关于它的缺陷报告。结果:这是一个灰色地带,并且可能继续是一个。使用宏定义通用数组大小函数,只是为了安全起见。
-
您需要将您的成员函数设为
static,这样它就不会依赖于隐式的this指针,并且可能会取消自己成为常量表达式的资格。 -
我现在没有时间给出答案,但这类似于this question
-
我在the FAQ on arrays 中添加了关于数组大小问题的部分,现在是 5.4。请注意@Columbo,由于他在这里的论点(现已删除):FAQ 的这一部分最初是由我编写的。你可以了解所有关于这个和那个的危险。 ;-)
标签: c++ gcc clang c++14 constexpr