【发布时间】:2016-12-15 11:58:51
【问题描述】:
为什么 C++ 编译器可以将函数声明为 constexpr,而不能声明为 constexpr?
例如:http://melpon.org/wandbox/permlink/AGwniRNRbfmXfj8r
#include <iostream>
#include <functional>
#include <numeric>
#include <initializer_list>
template<typename Functor, typename T, size_t N>
T constexpr reduce(Functor f, T(&arr)[N]) {
return std::accumulate(std::next(std::begin(arr)), std::end(arr), *(std::begin(arr)), f);
}
template<typename Functor, typename T>
T constexpr reduce(Functor f, std::initializer_list<T> il) {
return std::accumulate(std::next(il.begin()), il.end(), *(il.begin()), f);
}
template<typename Functor, typename T, typename... Ts>
T constexpr reduce(Functor f, T t1, Ts... ts) {
return f(t1, reduce(f, std::initializer_list<T>({ts...})));
}
int constexpr constexpr_func() { return 2; }
template<int value>
void print_constexpr() { std::cout << value << std::endl; }
int main() {
std::cout << reduce(std::plus<int>(), 1, 2, 3, 4, 5, 6, 7) << std::endl; // 28
std::cout << reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7}) << std::endl;// 28
const int input[3] = {1, 2, 3}; // 6
std::cout << reduce(std::plus<int>(), input) << std::endl;
print_constexpr<5>(); // OK
print_constexpr<constexpr_func()>(); // OK
//print_constexpr<reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})>(); // error
return 0;
}
输出:
28
28
6
5
2
为什么在这一行出错://print_constexpr<reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})>(); // error 即使对于 C++14 和 C++1z?
-
std::plus-constexpr T operator()( const T& lhs, const T& rhs ) const;(C++14 起) - constexpr: http://en.cppreference.com/w/cpp/utility/functional/plus -
constexpr initializer_list();(C++14 起) -initializer_list的构造是 constexpr:http://en.cppreference.com/w/cpp/utility/initializer_list/initializer_list
为什么编译器允许将reduce()标记为constexpr,但reduce()不能用作模板参数,即使传递给reduce()的所有参数在编译时都已知?
对于某些编译器也有同样的效果 - 支持 C++14 -std=c++14:
- x86 GCC 7.0.0
-std=c++1z -O3: http://melpon.org/wandbox/permlink/AGwniRNRbfmXfj8r - x86 gcc 4.9.2
-std=c++14 -O3: https://godbolt.org/g/wmAaDT - x86 gcc 6.1
-std=c++14 -O3: https://godbolt.org/g/WjJQE5 - x86 clang 3.5
-std=c++14 -O3: https://godbolt.org/g/DSCpYv - x86 clang 3.8
-std=c++14 -O3: https://godbolt.org/g/orSrgH - x86 Visual C++ - 您应该将代码复制粘贴到:http://webcompiler.cloudapp.net/
- ARM gcc 4.8.2、ARM64 gcc 4.8、PowerPC gcc 4.8、AVR gcc 4.5.3 - 不支持 C+14
-std=c++14
对于所有这些情况,编译OK,直到未使用的行://print_constexpr<reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})>(); // error
【问题讨论】:
-
"C++ 编译器"?哪个编译器?海合会?铛?微软?什么版本?
标签: c++ templates c++11 constexpr compile-time