Por que o compilador C ++ torna possível declarar uma função como constexpr, que não pode ser constexpr?
Por que o compilador C ++ torna possível declarar uma função como constexpr, que não pode ser constexpr?
Por exemplo: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;
}
Resultado:
28
28
6
5
2
Por que erro nesta linha://print_constexpr<reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})>(); // error
mesmo para C ++ 14 e C ++ 1z?
std::plus
- constexpr T operator()( const T& lhs, const T& rhs ) const;
(desde C ++ 14) -constexpr: http://en.cppreference.com/w/cpp/utility/functional/plusconstexpr initializer_list();
(desde C ++ 14) - construcot deinitializer_list
éconstexpr: http://en.cppreference.com/w/cpp/utility/initializer_list/initializer_listPor que o compilador permite marcarreduce()
Comoconstexpr
, masreduce()
não pode ser usado como parâmetro de modelo, mesmo que todos os parâmetros passados parareduce()
conhecido em tempo de compilação?
O mesmo efeito para alguns compiladores - queC ++ 14 suportado -std=c++14
:
-std=c++1z -O3
: http://melpon.org/wandbox/permlink/AGwniRNRbfmXfj8rx86 gcc 4.9.2-std=c++14 -O3
: https://godbolt.org/g/wmAaDTx86 gcc 6.1-std=c++14 -O3
: https://godbolt.org/g/WjJQE5x86 clang 3.5-std=c++14 -O3
: https://godbolt.org/g/DSCpYvx86 clang 3.8-std=c++14 -O3
: https://godbolt.org/g/orSrgHx86 Visual C ++ - você deve copiar e colar o código para:http://webcompiler.cloudapp.net/ARM gcc 4.8.2, ARM64 gcc 4.8, PowerPC gcc 4.8, AVR gcc 4.5.3 - não suporta C + 14-std=c++14
Para todos esses casos, compile OK, até a linha não utilizada://print_constexpr<reduce(std::plus<int>(), {1, 2, 3, 4, 5, 6, 7})>(); // error