2016-08-13 9 views
9

Nie mogę używać wartości constexpr w funkcji, w przeciwieństwie do zewnętrznej funkcji.Dlaczego nie mogę używać wartości constexpr w funkcji, ale mogę zrobić to samo w zakresie tej wartości?

  • można użyć auto ar1 = std::array<int, il.size()>(); w zakresie, w il jest zdefiniowana.

  • Ale nie mogę użyć { return std::array<T, il.size()>();} w constexpr -function il_to_array()

Dlaczego nie mogę używać wartości constexpr w funkcji, ale mogę zrobić to samo w zakresie bloku tej wartości?

http://ideone.com/5g0iRE

#include <iostream> 
#include <initializer_list> 
#include <array> 

constexpr size_t size_to_size(size_t v) { return v; } // 1 - OK 

template<typename T> 
constexpr size_t il_to_size(std::initializer_list<T> il) { return il.size(); } // 2 - OK 

// 3 - error 
template<typename T> 
constexpr auto il_to_array(std::initializer_list<T> il) {return std::array<T, il.size()>();} 

template<size_t N> 
void print_constexpr() { std::cout << N << std::endl; } 

int main() { 

    constexpr std::initializer_list<int> il = { 1, 2, 3 }; 
    print_constexpr<il.size()>(); // 0 - OK 

    print_constexpr< size_to_size(il.size()) >(); // 1 - OK 

    print_constexpr< il_to_size(il) >(); // 2 - OK 

    auto ar1 = std::array<int, il.size()>(); // OK - body of function: il_to_array() 

    //auto ar2 = il_to_array(il); // 3 - error 

    return 0; 
} 

Na przykład, nie widzimy, że szablon constexpr funkcja nie zawiedzie, nawet jeśli może to być lub nie być constexpr - zależy od T, ponieważ jedna z instancji może być constexpr: Why does the C++ compiler makes it possible to declare a function as constexpr, which can not be constexpr?

  • i można stwierdzić, że jeśli jest to szablon funkcji, może być specjalizacja którykolwiek: constexpr i braku constexpr.

  • I na podstawie SFINAE - jeśli używamy tylko constexpr -arguments następnie wystąpienie tylko constexpr -instance, i to nie ma znaczenia, że ​​nie- constexpr -function nie może być instancja.

Odpowiedz

8

Argumenty funkcji (constexpr) nie są constexpr.

constexpr funkcje mogą mieć podane argumenty, które nie były znane podczas kompilacji.

Więc po to ważne czy v jest znany w czasie kompilacji lub nie

constexpr size_t size_to_size(size_t v) { return v; } 

Ale Poniższa funkcja nie działa jak il nie constexpr i non parametr typu szablon wymaga być znany w czasie kompilacji:

template<typename T> 
constexpr auto il_to_array(std::initializer_list<T> il) {return std::array<T, il.size()>();} 

Jest to prawdą, nawet jeśli funkcja jest wywoływana tylko z argumentami znanymi podczas kompilacji.

+2

Err ... Nie jestem pewien, czy historia kończy się tutaj na nieszczęściach OP ... [Clang] (http://coliru.stacked-crooked.com/a/e5440da7ff6a1316) i [MSVC] (http: // /webcompiler.cloudapp.net/) nie skompilował kodu OP (działa tylko gcc). Odrzucają go, ponieważ nie uważają utworzenia 'std :: initializer_list ' 'constexpr' .. Które wierzę: ponieważ standard nie jest jasne o tym, że jest" constexpr ", z wyjątkiem jego funkcji członkowskich. Inna logika wspierająca, co jeśli 'T' nie można zainicjować jako' constexpr' w 'std :: initializer_list '? – WhiZTiM

+0

@WhiZTiM: Spójrz na [dlaczego-isnt-stdinitializer-list-defined-as-a-literal-type] (http://stackoverflow.com/questions/27496004/why-isnt-stdinitializer-list-defined-as- a-literal-ny? noredirect = 1 & lq = 1) dla tego błędu. – Jarod42

+0

Przeszukałem wszystkie linki do [dyskusji na forum] (https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/aA3BsR4ZuoE/discussion) ..I zgodnie z odpowiedzią Richarda Smitha, Clang i MSVC mają rację co do 'constexpr std :: initializer_list il = {1,2,3,4};' są źle sformułowane. – WhiZTiM

Powiązane problemy