Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env bash -vex
- WARN="-W -Wall -Wextra -Werror"
- g++ -x c++ - -std=gnu++1y $WARN -Ofast -o a <<__EOF && ./a && echo -e "\e[1;32msucceeded\e[0m" || echo -e "\e[1;31mfailed\e[0m"
- // http://stackoverflow.com/questions/16893992/
- #include <type_traits>
- #include <cstdlib>
- #if 0
- using A = float;
- using B = double;
- using C = long double;
- #elif 0
- struct A { A() = delete; ~A() = delete; A(A const &) = delete; A(A &&) = delete; A & operator = (A const &) = delete; A & operator = (A &&) = delete; };
- struct B { B() = delete; ~B() = delete; B(B const &) = delete; B(B &&) = delete; B & operator = (B const &) = delete; B & operator = (B &&) = delete; };
- struct C { C() = delete; ~C() = delete; C(C const &) = delete; C(C &&) = delete; C & operator = (C const &) = delete; C & operator = (C &&) = delete; };
- #elif 1
- struct A {};
- struct B {};
- struct C {};
- #endif
- struct AA
- {
- explicit operator A const & () const;
- explicit operator A & ();
- explicit operator B (); // note '=9.a' below
- };
- struct BB
- {
- explicit operator B const & () const;
- explicit operator B & ();
- explicit operator A () const; // note '=9.c' below
- };
- struct CC
- {
- explicit operator C const & () const;
- explicit operator C & ();
- };
- #if 0
- template< typename From, typename To, typename Enabler = void >
- struct is_explicitly_convertible
- : std::false_type
- {
- };
- namespace details
- {
- template< typename T >
- auto retval() -> T;
- }
- template< typename From, typename To >
- struct is_explicitly_convertible< From, To, typename std::enable_if< (std::is_fundamental< typename std::remove_reference< From >::type >::value && std::is_fundamental< typename std::remove_reference< decltype(static_cast< To >(details::retval< From >())) >::type >::value) >::type >
- : std::true_type
- {
- };
- template< typename From, typename To >
- struct is_explicitly_convertible< From, To, typename std::enable_if< std::is_member_function_pointer< decltype(&std::remove_reference< From >::type::operator To) >::value >::type >
- : std::integral_constant< bool, ((std::is_const< typename std::remove_reference< From >::type >::value && std::is_same< To (std::remove_reference< From >::type::*)() const, decltype(&std::remove_reference< From >::type::operator To) >::value) || !std::is_const< typename std::remove_reference< From >::type >::value) && (!std::is_lvalue_reference< To >::value || std::is_const< typename std::remove_reference< To >::type >::value || !std::is_const< typename std::remove_reference< From >::type >::value) >
- {
- };
- #elif 0
- template< typename From, typename To, typename Enabler = void >
- struct is_explicitly_convertible
- : std::false_type
- {
- };
- template< typename From, typename To >
- struct is_explicitly_convertible< From, To, typename std::conditional< true, void, decltype(static_cast< To >(std::declval< From >())) >::type >
- : std::true_type
- {
- };
- #elif 0
- template< class U, class T >
- struct is_explicitly_convertible
- {
- enum : bool { value = (std::is_constructible< T, U >::value && !std::is_convertible< U, T >::value) };
- };
- #elif 1
- template< typename From, typename To >
- struct is_explicitly_convertible
- : std::is_constructible< To, From >
- {
- };
- #endif
- namespace
- {
- 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*");
- }
- struct X { X(X &&) = delete; }; struct Y { explicit operator X (); }; static_assert(!is_explicitly_convertible< Y, X >::value, "?");
- int main()
- {
- return EXIT_SUCCESS;
- }
- __EOF
Advertisement
Add Comment
Please, Sign In to add comment