2016-05-25 16 views
7

Hiện tại tôi đang viết lại/mở rộng thư viện tiện ích C++ của mình với tính năng C++ 11 mới. Một trong những bổ sung mới là một lớp mẫu cung cấp giá trị tối đa của một tập hợp các số, hy vọng tại thời gian biên dịch.Có thể kiểm tra xem giá trị const có được biết tại thời gian biên dịch không?

template<typename T, T... Xs> class ConstMax 
{ 
private: 
    template<typename... Ts> static constexpr T Max(Ts... xs); 

    template<typename Tx> static constexpr T Max(Tx x) 
    { 
     return x; 
    } 

    template<typename T1, typename T2, typename... Ts> static constexpr T Max(T1 x, T2 y, Ts... xs) 
    { 
     return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); 
    } 

public: 
    static const T Value = Max(Xs...); 
}; 

Một sử dụng ví dụ của lớp này:

int max = ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value; 

đây một ví dụ khác mà có thể làm cho nó khó khăn hơn để xác minh nếu ConstMax < ...> :: Giá trị thực sự đã được đánh giá trong thời gian biên dịch:

template<typename... Ts> class Variant 
{ 
public: 
    static const size_t MaxValueSize = ConstMax<size_t, sizeof(Ts)...>::Value; 
}; 

Kết quả nào trong số max = 90. Tôi bước máng mã này bằng cách sử dụng gdb và có vẻ như không có cuộc gọi chức năng nào được thực hiện trong khi gán tối đa.

Câu hỏi của tôi:

  1. Tôi có thể an toàn cho rằng ConstMax<...>::Value luôn được biết đến tại thời gian biên dịch?
  2. Có cách nào để kiểm tra xem constexpr chức năng/phương pháp được đánh giá vào thời gian biên dịch không?
  3. Tôi hiểu các thành viên/phương pháp/chức năng được xác định là constexpr không nhất thiết phải được đánh giá trong thời gian biên dịch, thực tế là Value được định nghĩa là static const thay đổi bất cứ điều gì về điều này hoặc tôi tốt hơn việc triển khai trường hợp cụ thể này làm lớp mẫu đệ quy?

Trả lời

3
  1. Tôi có thể an toàn cho rằng ConstMax < ...> :: Giá trị luôn được biết đến tại thời gian biên dịch?

Có, vì nó được khởi tạo với biểu thức không đổi. Nhưng tôi muốn sửa đổi Value thành constexpr thay vì chỉ const.

  1. Có cách nào để kiểm tra xem các hàm/phương pháp constexpr được đánh giá tại thời gian biên dịch không?

Có. Hãy thử sử dụng chúng trong biểu thức constexpr. Nếu nó hoạt động, chúng đang được đánh giá tại thời gian biên dịch. Nếu nó không biên dịch, thì nó không được đánh giá tại thời gian biên dịch.

  1. Tôi hiểu các thành viên/phương pháp/chức năng định nghĩa là constexpr không nhất thiết phải đánh giá trong thời gian biên dịch, thực hiện thực tế là giá trị gia tăng được xác định như là const tĩnh thay đổi bất cứ điều gì về vấn đề này hoặc là Tôi tốt hơn khi thực hiện trường hợp cụ thể này như là một lớp mẫu đệ quy?

Nếu bạn sử dụng thành viên trong biểu thức không đổi, bạn buộc phải đánh giá thành viên trong thời gian biên dịch. Vì vậy, nếu bạn quan tâm, tôi chỉ cần chắc chắn để đánh giá chúng trong các biểu thức không đổi (thông qua constexpr).

+0

Cảm ơn bạn đã phản hồi nhanh chóng. Tôi đã ưa thích cách tiếp cận constexpr nhiều hơn sau đó sử dụng các mẫu đệ quy, tốt để biết điều này không ảnh hưởng đến thời gian đánh giá. – Charlie

+0

Làm cách nào để bạn biết liệu hàm có phải là constexpr tại thời gian biên dịch hay không bằng cách gọi hàm đó? Nếu một trong các đối số không phải là constexpr cuộc gọi sẽ thất bại cũng phải không? – Alex

+0

@ Alex: Có, nếu bạn cố gắng đánh giá hàm trong một biểu thức không đổi, và nó không phải là một biểu thức liên tục, việc biên dịch sẽ thất bại. – Cornstalks

3

Để kiểm tra xem một biểu thức là constexpr (ví dụ, biểu thức hằng số), bạn có thể sử dụng std::integral_constant loại đặc điểm như sau:

#include <iostream> 
#include <type_traits> 

template<typename T, T... Xs> class ConstMax { 
    template<typename... Ts> static constexpr T Max(Ts... xs); 
    template<typename Tx> static constexpr T Max(Tx x) { return x;} 
    template<typename T1, typename T2, typename... Ts> 
    static constexpr T 
    Max(T1 x, T2 y, Ts... xs) { 
     return y > x ? Max<T2, Ts...>(y, xs...) : Max<T1, Ts...>(x, xs...); 
    } 
public: 
    static const T Value = Max(Xs...); 
}; 

int main() { 
std::cout << std::integral_constant<int, ConstMax<int, 1, 8, 66, 32, 90, 12, 33>::Value>::value << std::endl; 
} 

Live Demo

Nếu nó không phải constexpr nó sẽ phá vỡ quá trình biên dịch.

+0

Cảm ơn bạn, điều này sẽ trở thành một phần mở rộng thực sự tốt đẹp cho các bài kiểm tra đơn vị của tôi. – Charlie

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