我有以下示例:
#include <cstdint>
template<typename T>
struct a_size {
constexpr static std::size_t size() { return sizeof(T); }
};
template<typename T>
constexpr std::size_t foo(T const& t) {
constexpr auto result = a_size<decltype(t)>::size();
return result;
}
template<typename T>
constexpr std::size_t bar(T const& t) {
constexpr auto result = foo(t);
return result;
}
int main() {
constexpr auto r = bar('c');
return r;
}
使用g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
进行编译时,一切似乎都很好。但是,当我使用clang++
(版本:clang version 10.0.0 (https://github.com/llvm-mirror/clang.git df2d9221d77042d6b07a6025edf9e810f1801ef5) (https://github.com/llvm-mirror/llvm.git a1e2fd38b595bd636661ac7416961e029c7e1689)
)进行编译时,出现以下错误:
main.cc:16:33: error: constexpr variable 'result' must be initialized by a constant expression
constexpr auto result = foo(t);
~~~~^~
main.cc:21:24: note: in instantiation of function template specialization 'bar<char>' requested here
constexpr auto r = bar('c');
^
1 error generated.
我在godbolt.org
和clang 8.0.0
的{{1}}上观察到类似的行为,该示例有效,但是,clang trunk
和{{1 }}。
GCC
9.2.0
trunk
的结果未标记为clang++ -std=c++17 main.cc -o main.run
。问题在于原因。)g++ -std=c++17 main.cc -o main.run
还是constexpr
中?foo(t)
中的引用(constexpr
)才能解决问题,而GCC/G++
不再产生编译错误?显然,删除中间变量Clang
可解决此问题(如David Ledger所建议)。但这不能回答其他问题。更不用说某些用例可能需要这样的中间变量。