tập kiểm tra của bạn là một liên kết off-site và đã thay đổi kể từ khi ban bài viết của bạn, vì vậy tôi sẽ sao chép nguyên văn bài kiểm tra-set tôi đang nói về ở đây:
static_assert(is_explicitly_convertible< double, double >::value, "1");
static_assert(is_explicitly_convertible< double &, double >::value, "2");
static_assert(is_explicitly_convertible< double const, double >::value, "3");
static_assert(is_explicitly_convertible< double const &, double >::value, "4");
static_assert(is_explicitly_convertible< double, double const & >::value, "5");
static_assert(is_explicitly_convertible< double &, double const & >::value, "6");
static_assert(is_explicitly_convertible< double const, double const & >::value, "7");
static_assert(is_explicitly_convertible< double const &, double const & >::value, "8");
static_assert(!is_explicitly_convertible< double, double & >::value, "9"); // not a ref
static_assert(is_explicitly_convertible< double &, double & >::value, "10");
static_assert(!is_explicitly_convertible< double const, double & >::value, "11");
static_assert(!is_explicitly_convertible< double const &, double & >::value, "12");
static_assert(is_explicitly_convertible< double, double const >::value, "13");
static_assert(is_explicitly_convertible< double &, double const >::value, "14");
static_assert(is_explicitly_convertible< double const, double const >::value, "15");
static_assert(is_explicitly_convertible< double const &, double const >::value, "16");
static_assert(is_explicitly_convertible< AA const &, A const & >::value, "=&1.a");
static_assert(is_explicitly_convertible< CC const &, C const & >::value, "=&1.b");
static_assert(is_explicitly_convertible< BB const &, B const & >::value, "=&1.c");
static_assert(!is_explicitly_convertible< AA const &, A & >::value, "&1.a");
static_assert(!is_explicitly_convertible< CC const &, C & >::value, "&1.b");
static_assert(!is_explicitly_convertible< BB const &, B & >::value, "&1.c");
static_assert(is_explicitly_convertible< AA const, A const & >::value, "=1.a");
static_assert(is_explicitly_convertible< CC const, C const & >::value, "=1.b");
static_assert(is_explicitly_convertible< BB const, B const & >::value, "=1.c");
//static_assert(!is_explicitly_convertible< AA const, A >::value, "=2.a"); // ???????????????
//static_assert(!is_explicitly_convertible< CC const, C >::value, "=2.b");
//static_assert(!is_explicitly_convertible< BB const, B >::value, "=2.c");
static_assert(!is_explicitly_convertible< AA const, A & >::value, "=3.a"); // good!
static_assert(!is_explicitly_convertible< CC const, C & >::value, "=3.b"); //
static_assert(!is_explicitly_convertible< BB const, B & >::value, "=3.c"); //
static_assert(!is_explicitly_convertible< AA const, A && >::value, "=4.a"); // not interesting
static_assert(!is_explicitly_convertible< CC const, C && >::value, "=4.b"); //
static_assert(!is_explicitly_convertible< BB const, B && >::value, "=4.c"); //
static_assert(!is_explicitly_convertible< AA const, B const & >::value, "=5.a");
static_assert(!is_explicitly_convertible< AA const, C const & >::value, "=5.b");
static_assert(!is_explicitly_convertible< BB const, A const & >::value, "=5.c");
static_assert(!is_explicitly_convertible< BB const, C const & >::value, "=6.a");
static_assert(!is_explicitly_convertible< CC const, A const & >::value, "=6.b");
static_assert(!is_explicitly_convertible< CC const, B const & >::value, "=6.c");
static_assert(!is_explicitly_convertible< AA const, B & >::value, "=7.a");
static_assert(!is_explicitly_convertible< AA const, C & >::value, "=7.b");
static_assert(!is_explicitly_convertible< BB const, A & >::value, "=7.c");
static_assert(!is_explicitly_convertible< BB const, C & >::value, "=8.a");
static_assert(!is_explicitly_convertible< CC const, A & >::value, "=8.b");
static_assert(!is_explicitly_convertible< CC const, B & >::value, "=8.c");
static_assert(!is_explicitly_convertible< AA const, B >::value, "=9.a"); // very subtle moment (see class AA above)
static_assert(!is_explicitly_convertible< AA const, C >::value, "=9.b");
static_assert(is_explicitly_convertible< BB const, A >::value == std::is_constructible< A, A && >::value, "=9.c"); // (see class BB above)
static_assert(!is_explicitly_convertible< BB const, C >::value, "=10.a");
static_assert(!is_explicitly_convertible< CC const, A >::value, "=10.b");
static_assert(!is_explicitly_convertible< CC const, B >::value, "=10.c");
static_assert(is_explicitly_convertible< AA, A & >::value, "~1.a");
static_assert(is_explicitly_convertible< CC, C & >::value, "~1.b");
static_assert(is_explicitly_convertible< BB, B & >::value, "~1.c");
//static_assert(!is_explicitly_convertible< AA, A >::value, "~2.a"); // ???????????????
//static_assert(!is_explicitly_convertible< CC, C >::value, "~2.b");
//static_assert(!is_explicitly_convertible< BB, B >::value, "~2.c");
static_assert(is_explicitly_convertible< AA, A const & >::value, "~3.a"); // convertible
static_assert(is_explicitly_convertible< CC, C const & >::value, "~3.b"); //
static_assert(is_explicitly_convertible< BB, B const & >::value, "~3.c"); //
static_assert(!is_explicitly_convertible< AA, B const & >::value, "~4.a");
static_assert(!is_explicitly_convertible< AA, C const & >::value, "~4.b");
static_assert(!is_explicitly_convertible< BB, A const & >::value, "~4.c");
static_assert(!is_explicitly_convertible< BB, C const & >::value, "~5.a");
static_assert(!is_explicitly_convertible< CC, A const & >::value, "~5.b");
static_assert(!is_explicitly_convertible< CC, B const & >::value, "~5.c");
static_assert(std::is_convertible< double, double const & >::value, "5*");
static_assert(!std::is_convertible< double, double & >::value, "9*");
Nếu bạn avail của gcc 4.7.2 (và có lẽ trước đó, tôi đã không kiểm tra) thì C++ 11 thư viện chuẩn giải quyết vấn đề:
std::is_explicitly_convertible<From,To>
được định nghĩa trong <type_traits>
Tuy nhiên, sau đó bạn sẽ được availing của một error trong đó phiên bản của C++ 11 thư viện chuẩn. Mẫu đặc điểm này không nên có ở đó, bởi vì nó đã bị xóa khỏi Tiêu chuẩn theo N3047 (2010).
Nếu bạn ở trên gcc 4.8.1 (hoặc có thể 4.8; tôi chưa kiểm tra) thì đặc điểm này là không còn trong thư viện nữa, và nếu bạn muốn, bạn phải cuộn lại.
Nhưng nó sẽ chỉ là con người để kiểm tra việc định nghĩa trong gcc 4.7.2 của <type_traits>
cho một sự khởi đầu, và làm điều đó cho thấy rằng người thực hiện GNU coi là đặc điểm là không có gì nhưng nghịch đảo của std::is_constructible<To,From>
:
/// is_explicitly_convertible
template<typename _From, typename _To>
struct is_explicitly_convertible
: public is_constructible<_To, _From>
{ };
Người ta cũng có thể nghĩ rằng: Nhưng tất nhiên.
Vậy tại sao điều đó sẽ không xảy ra? N3047 giải thích:
Câu hỏi còn lại là, theo đó cách nào cũng bị ảnh hưởng is_explicitly_convertible
đặc điểm cần được sửa chữa.Các lựa chọn cơ bản là:
- Fix
is_explicitly_convertible
bằng cách quay lại biểu static_cast hiện tại, không còn làm is_explicitly_convertible
phụ thuộc vào is_constructible
.
- Xóa
is_explicitly_convertible
khỏi tiêu chuẩn.
Lựa chọn đầu tiên được xem xét, nhưng hóa ra là có tồn tại những hiểu biết khá khác về những gì "chuyển đổi rõ ràng" thực sự có ý nghĩa. Trong khi một số người tin rằng static_cast
thể hiện chính xác điều này, những người khác tin rằng số is_constructible
cố định cũng sẽ mang lại ý nghĩa tốt hơn cho is_explicitly_convertible
. Do đó bài viết này đề nghị xóa is_explicitly_convertible
khỏi bản nháp đang hoạt động. Điều này sẽ không gây hại bây giờ, bởi vì không có gì phụ thuộc vào định nghĩa đặc biệt đó. Và nếu nó chỉ ra, rằng các đặc điểm vẫn sẽ hữu ích, nó có thể được thêm vào trong một phiên bản khác của tiêu chuẩn.
Không có lỗi được biết đến trong định nghĩa đó, nhưng đã có quan điểm trái ngược về việc liệu ý nghĩa của "một cách rõ ràng mui trần" mà nó hệ thống hóa là một trong những quyền: -
- D1)
From
là một cách rõ ràng mui trần để To
= df To
là constructible từ From
- D2)
From
là rõ ràng mui trần để To
= df From
có thể được tĩnh đúc để To
Tôi sẽ không tranh luận về vấn đề này (thậm chí tôi chưa từng biết sự khác biệt là gì), nhưng sẽ đề nghị bạn chỉ cần thanh toán tiền của bạn và lựa chọn.
Nếu bạn ưu tiên D1) thì bạn có thể chỉ cần định nghĩa đặc điểm từ gcc 4.7.2 <type_traits>
, như trên.
Nếu bạn ưu tiên D2, bạn có thể đạo văn và điều chỉnh định nghĩa của std::is_convertible<From,To>
từ gcc 4.8.1 <type_traits>
. Định nghĩa này viện dẫn các chức năng phụ trợ bên trong mà bạn sẽ phải theo dõi.Sự thích nghi bạn muốn sẽ thay đổi thử nghiệm SFINAE cho From
có thể được ngầm đúc để To
đến một thử nghiệm cho From
có thể static_cast
để To
; và điều đó có nghĩa thay thế:
template<typename _From1, typename _To1>
static decltype(__test_aux<_To1>(std::declval<_From1>()), __one())
__test(int);
với:
template<typename _From1, typename _To1>
static decltype(__test_aux<_To1>(static_cast<_To1>(std::declval<_From1>())), __one())
__test(int);
Một phiên bản cắt giảm của định nghĩa này (bỏ qua trường hợp như From
là void
và To
là một chức năng hoặc mảng loại) mà sẽ làm cho các loại được kiểm tra trong số static_assert
của bạn:
template<typename From, typename To>
struct is_explicitly_convertible
{
template<typename T>
static void f(T);
template<typename F, typename T>
static constexpr auto test(int) ->
decltype(f(static_cast<T>(std::declval<F>())),true) {
return true;
}
template<typename F, typename T>
static constexpr auto test(...) -> bool {
return false;
}
static bool const value = test<From,To>(0);
};
Định nghĩa D1 hoặc định nghĩa D2 cắt xuống duy trì tất cả 63 trong số static_assert
giây của bạn. (tôi biên soạn với g ++ 4.7.2 và 4.8.1, -g;-O0;-Wall;-std=c++11
, và cũng với các -std=gnu++1y
mà bạn sử dụng)
giải pháp mới nhất của bạn cho thấy bạn đã thực hiện theo cách riêng của mình cho nhà trường D2, với một khác nhau phong cách thực hiện.
Trong hai, cho đến khi tôi tìm thấy một cái gì đó xảy ra với nó, tôi muốn định nghĩa D1, theo gcc 4.7.2, chỉ vì nó là nhiều đơn giản và đặc biệt là một dẫn xuất tầm thường của std::is_constructible
.
Có lẽ tôi hiểu nhầm câu hỏi, nhưng bạn có thể thực hiện 'dynamic_cast (FROM & val)', nó sẽ ném 'std :: bad_cast' nếu chuyển đổi không đủ điều kiện. –
@ H2CO3 Giả sử, câu hỏi đó là về vấn đề thời gian biên dịch. – Orient
Khi bạn muốn tìm kiếm toán tử chuyển đổi rõ ràng, nhiệm vụ của bạn dường như đun sôi xuống [xác định xem một lớp T có một hàm thành viên với một chữ ký đã cho] hay không (http://stackoverflow.com/q/87372/1362568). Có nhiều câu trả lời ở đó, kể cả một trong các câu trả lời của tôi. –