2012-12-25 31 views
8

Tôi đã sau đoạnstd :: is_default_constructible <T> lỗi, nếu constructor là tin

#include <type_traits> 
#include <boost/type_traits.hpp> 

class C { C() { } }; 

int main() 
{ 
    static_assert(!boost::has_trivial_default_constructor<C>::value, "Constructible"); 
    static_assert(!std::is_default_constructible<C>::value, "Constructible"); 
} 

điều kiện không bằng nhau, nhưng điều kiện đầu tiên công trình xây dựng tốt và thứ hai cho lỗi, constructor đó là tư nhân. Trình biên dịch gcc 4.7 ... Vậy, đây có phải là lỗi gcc hay được định nghĩa theo tiêu chuẩn?

http://liveworkspace.org/code/NDQyMD $ 5

OK. Từ điều kiện này thực sự bất bình đẳng - chúng ta có thể sử dụng một cái gì đó như thế này

#include <type_traits> 
#include <boost/type_traits.hpp> 

class C { private: C() noexcept(false) { } }; 

int main() 
{ 
    static_assert(!boost::has_nothrow_constructor<C>::value, "Constructible"); 
    static_assert(!std::is_nothrow_constructible<C>::value, "Constructible"); 
} 

http://liveworkspace.org/code/NDQyMD $ 24

Dù sao, tôi biết, static_assert rằng không nên thất bại, kể từ khi loại được thực sự không mặc constructible/không nothrow constructible. Câu hỏi là: TẠI SAO có lỗi biên dịch, không phải bởi khẳng định tĩnh của tôi?

+2

Tôi hiểu ý của bạn bây giờ. Nó trông giống như một lỗi sau đó. – dasblinkenlight

+0

Lưu ý rằng hai đặc điểm kiểm tra các thuộc tính khác nhau. – Xeo

+0

@Xeo ok ... và làm thế nào về 'has_nothrow_constructor' và' is_nothrow_constructible'? – ForEveR

Trả lời

5

Trông giống như lỗi trình biên dịch. Hãy xem ví dụ sau của SFINAE (thực hiện tương tự được sử dụng trong type_traits tiêu đề g++ 's)

#include <type_traits> 

class Private 
{ 
    Private() 
    { 

    } 
}; 

class Delete 
{ 
    Delete() = delete; 
}; 

struct is_default_constructible_impl 
{ 
    template<typename T, typename = decltype(T())> 
    static std::true_type test(int); 

    template<typename> 
    static std::false_type test(...); 
}; 

template <class T> 
struct is_default_constructible: decltype(is_default_constructible_impl::test<T>(0)) 
{ 

}; 

int main() 
{ 
    static_assert(is_default_constructible<Private>::value, "Private is not constructible"); 
    static_assert(is_default_constructible<Delete>::value, "Delete is not constructible"); 
} 

Các khẳng định thứ hai công trình như mong đợi, chúng ta không thể suy ra Delete loại, kể từ khi lớp học chỉ có một constructor xóa. Nhưng khi trình biên dịch cố gắng suy ra loại Private(), nó cho lỗi: Private::Private() is private. Vì vậy, chúng ta có hai lớp với hàm tạo riêng, nhưng một trong số chúng mang lại lỗi và thứ hai là không. Tôi nghĩ rằng, hành vi này là sai, nhưng tôi không thể tìm thấy xác nhận trong tiêu chuẩn.

P.S. tất cả các mã trình bày được biên dịch bởi clang mà không có bất kỳ lỗi nào.

+0

Tôi không hiểu ... 'Riêng tư 'chỉ đơn giản là * không * mặc định là có thể cấu hình được, phải không? Có, nó có một hàm tạo mặc định nhưng tất nhiên là không thể sử dụng được trong ngữ cảnh 'is_default_constructible_impl :: test' để khẳng định không thành công, và tôi nghĩ rằng việc thực hiện đặc điểm này là hoàn toàn chính xác. - Nhưng thành thật mà nói, tiêu chuẩn dường như không đề cập rõ ràng trong §20.9.4.3 liệu các nhà thầu có được cho là công khai hay không; Tôi chỉ nghĩ rằng nó có ý nghĩa hơn để yêu cầu điều này. –

+0

@KonradRudolph, tôi đã giải thích không chính xác. Biên dịch thất bại khi trình biên dịch cố gắng suy ra loại 'Private()', không phải bằng khẳng định tĩnh. Hay tôi đã hiểu lầm bạn? – soon

+0

@KonradRudolph: Xác nhận không thành công. 'std :: is_constructible' không thành công. Các tiêu chuẩn không yêu cầu các nhà xây dựng được công khai (trong §20.9.4.3/6) nhưng tôi không nghĩ rằng nó có nghĩa là các loại đặc điểm nên gây ra một lỗi biên dịch. – hpsMouse

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