2016-08-13 13 views
9

Tôi không thể sử dụng giá trị constexpr trong hàm, trái ngược với bên ngoài của hàm.Tại sao tôi không thể sử dụng giá trị constexpr trong hàm, nhưng tôi có thể làm tương tự trong phạm vi giá trị này?

  • Tôi có thể sử dụng auto ar1 = std::array<int, il.size()>(); trong phạm vi nơi il được xác định.

  • Nhưng tôi không thể sử dụng { return std::array<T, il.size()>();} trong constexpr -function il_to_array()

Tại sao tôi không thể sử dụng giá trị constexpr trong chức năng, nhưng tôi có thể làm điều tương tự trong phạm vi khối giá trị này?

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; 
} 

Ví dụ, có chúng ta thấy, rằng mẫu-constexpr chức năng sẽ không thất bại, thậm chí nếu nó có thể hoặc có thể không constexpr - phụ thuộc của T, bởi vì một trong những ví dụ có thể constexpr: Why does the C++ compiler makes it possible to declare a function as constexpr, which can not be constexpr?

  • và nó có thể kết luận rằng nếu đây là một mẫu chức năng, nó có thể là chuyên môn hóa bất kỳ: constexpr và phi constexpr.

  • Và trên cơ sở SFINAE - nếu chúng ta chỉ sử dụng constexpr -arguments sau đó instantiates chỉ constexpr -instance, và nó không quan trọng mà không constexpr -function không thể được khởi tạo.

Trả lời

8

Đối số của hàm (constexpr) không phải là constexpr.

constexpr chức năng có thể được đưa ra các đối số không được biết tại thời gian biên dịch.

Vì vậy, sau đây là hợp lệ hay không v được biết đến tại thời gian biên dịch hay không

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

Nhưng sau chức năng không hoạt động như il không constexpr và tham số kiểu mẫu không đòi hỏi phải được biết đến tại thời gian biên dịch:

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

Điều này đúng ngay cả khi chức năng chỉ được gọi với các đối số đã biết lúc biên dịch.

+2

Err ... Tôi không chắc chắn câu chuyện kết thúc ở đây vì những tai ương của OP ... [Clang] (http://coliru.stacked-crooked.com/a/e5440da7ff6a1316) và [MSVC] (http://webcompiler.cloudapp.net/) không biên dịch mã OP (chỉ có gcc). Họ từ chối nó bởi vì họ không xem xét việc tạo ra 'std :: initializer_list ' a 'constexpr' .. Tôi tin rằng: vì tiêu chuẩn không rõ ràng về nó là' constexpr' ngoại trừ chức năng thành viên của nó. Một logic hỗ trợ khác, nếu 'T' không thể khởi tạo thành' constexpr' trong 'std :: initializer_list ' thì sao? – WhiZTiM

+0

@WhiZTiM: Xem [why-isnt-stdinitializer-list-defined-as-a-literal-type] (http://stackoverflow.com/questions/27496004/why-isnt-stdinitializer-list-defined-as- a-literal-type? noredirect = 1 & lq = 1) cho lỗi đó. – Jarod42

+0

Tôi đã xem hết các liên kết đến [thảo luận diễn đàn] (https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/aA3BsR4ZuoE/discussion) ..Và theo phản ứng của Richard Smith, Clang và MSVC là chính xác về 'constexpr std :: initializer_list il = {1,2,3,4}; 'bị ốm. – WhiZTiM

Các vấn đề liên quan