Commit b3618b71 by Daniel Krugler Committed by Paolo Carlini

type_traits (common_time): Provide "SFINAE-friendly" implementation.

2012-10-09  Daniel Krugler  <daniel.kruegler@googlemail.com>

	* include/std/type_traits (common_time): Provide "SFINAE-friendly"
	implementation.
	(__success_type, __failure_type): Fix.
	* include/std/chrono (common_type): Likewise for the chrono::time_point
	specialization.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: New.
	* testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc:
	Likewise.
	* testsuite/20_util/duration/requirements/sfinae_friendly_1.cc:
	Likewise.
	* testsuite/20_util/common_type/requirements/typedefs-1.cc: Adjust wrt
	LWG 2141.
	* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust
	dg-error line numbers.
	* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
	* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.
	* testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Likewise.
	* testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
	Likewise.
	* testsuite/20_util/declval/requirements/1_neg.cc: Likewise.

	* testsuite/20_util/result_of/sfinae_friendly_1.cc: Trivial stylistic
	tweaks.
	* testsuite/20_util/result_of/sfinae_friendly_2.cc: Likewise.

From-SVN: r192276
parent 71111e6b
2012-10-09 Daniel Krugler <daniel.kruegler@googlemail.com>
* include/std/type_traits (common_time): Provide "SFINAE-friendly"
implementation.
(__success_type, __failure_type): Fix.
* include/std/chrono (common_type): Likewise for the chrono::time_point
specialization.
* testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: New.
* testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc:
Likewise.
* testsuite/20_util/duration/requirements/sfinae_friendly_1.cc:
Likewise.
* testsuite/20_util/common_type/requirements/typedefs-1.cc: Adjust wrt
LWG 2141.
* testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust
dg-error line numbers.
* testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise.
* testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise.
* testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Likewise.
* testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc:
Likewise.
* testsuite/20_util/declval/requirements/1_neg.cc: Likewise.
* testsuite/20_util/result_of/sfinae_friendly_1.cc: Trivial stylistic
tweaks.
* testsuite/20_util/result_of/sfinae_friendly_2.cc: Likewise.
2012-10-09 Andrew MacLeod <amacleod@redhat.com> 2012-10-09 Andrew MacLeod <amacleod@redhat.com>
PR libstdc++/54861 PR libstdc++/54861
......
...@@ -69,33 +69,53 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -69,33 +69,53 @@ namespace std _GLIBCXX_VISIBILITY(default)
} }
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 20.11.4.3 specialization of common_type (for duration)
template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2> // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
struct common_type<chrono::duration<_Rep1, _Period1>,
chrono::duration<_Rep2, _Period2>> template<typename _CT, typename _Period1, typename _Period2>
struct __duration_common_type_wrapper
{ {
private: private:
typedef __static_gcd<_Period1::num, _Period2::num> __gcd_num; typedef __static_gcd<_Period1::num, _Period2::num> __gcd_num;
typedef __static_gcd<_Period1::den, _Period2::den> __gcd_den; typedef __static_gcd<_Period1::den, _Period2::den> __gcd_den;
typedef typename common_type<_Rep1, _Rep2>::type __cr; typedef typename _CT::type __cr;
typedef ratio<__gcd_num::value, typedef ratio<__gcd_num::value,
(_Period1::den / __gcd_den::value) * _Period2::den> __r; (_Period1::den / __gcd_den::value) * _Period2::den> __r;
public: public:
typedef chrono::duration<__cr, __r> type; typedef __success_type<chrono::duration<__cr, __r>> type;
}; };
// 20.11.4.3 specialization of common_type (for time_point) template<typename _Period1, typename _Period2>
template<typename _Clock, typename _Dur1, typename _Dur2> struct __duration_common_type_wrapper<__failure_type, _Period1, _Period2>
struct common_type<chrono::time_point<_Clock, _Dur1>, { typedef __failure_type type; };
chrono::time_point<_Clock, _Dur2>>
{
private:
typedef typename common_type<_Dur1, _Dur2>::type __ct;
public: template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2>
typedef chrono::time_point<_Clock, __ct> type; struct common_type<chrono::duration<_Rep1, _Period1>,
chrono::duration<_Rep2, _Period2>>
: public __duration_common_type_wrapper<typename __member_type_wrapper<
common_type<_Rep1, _Rep2>>::type, _Period1, _Period2>::type
{ };
// 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly)
template<typename _CT, typename _Clock>
struct __timepoint_common_type_wrapper
{
typedef __success_type<chrono::time_point<_Clock, typename _CT::type>>
type;
}; };
template<typename _Clock>
struct __timepoint_common_type_wrapper<__failure_type, _Clock>
{ typedef __failure_type type; };
template<typename _Clock, typename _Duration1, typename _Duration2>
struct common_type<chrono::time_point<_Clock, _Duration1>,
chrono::time_point<_Clock, _Duration2>>
: public __timepoint_common_type_wrapper<typename __member_type_wrapper<
common_type<_Duration1, _Duration2>>::type, _Clock>::type
{ };
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
namespace chrono namespace chrono
......
...@@ -133,6 +133,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -133,6 +133,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef struct { char __arr[2]; } __two; typedef struct { char __arr[2]; } __two;
}; };
// For several sfinae-friendly trait implementations we transport both the
// result information (as the member type) and the failure information (no
// member type). This is very similar to std::enable_if, but we cannot use
// them, because we need to derive from them as an implementation detail.
template<typename _Tp>
struct __success_type
{ typedef _Tp type; };
struct __failure_type
{ };
// primary type categories. // primary type categories.
template<typename> template<typename>
...@@ -1771,25 +1783,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1771,25 +1783,70 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct conditional<false, _Iftrue, _Iffalse> struct conditional<false, _Iftrue, _Iffalse>
{ typedef _Iffalse type; }; { typedef _Iffalse type; };
/// common_type /// common_type
template<typename... _Tp> template<typename... _Tp>
struct common_type; struct common_type;
// sfinae-friendly common_type implementation:
struct __do_common_type_impl
{
template<typename _Tp, typename _Up>
static __success_type<typename decay<
decltype(true ? std::declval<_Tp>() : std::declval<_Up>())
>::type> _S_test(int);
template<typename, typename>
static __failure_type _S_test(...);
};
template<typename _Tp, typename _Up>
struct __common_type_impl
: private __do_common_type_impl
{
typedef decltype(_S_test<_Tp, _Up>(0)) type;
};
struct __do_member_type_wrapper
{
template<typename _Tp>
static __success_type<typename _Tp::type> _S_test(int);
template<typename>
static __failure_type _S_test(...);
};
template<typename _Tp>
struct __member_type_wrapper
: private __do_member_type_wrapper
{
typedef decltype(_S_test<_Tp>(0)) type;
};
template<typename _CTp, typename... _Args>
struct __expanded_common_type_wrapper
{
typedef common_type<typename _CTp::type, _Args...> type;
};
template<typename... _Args>
struct __expanded_common_type_wrapper<__failure_type, _Args...>
{ typedef __failure_type type; };
template<typename _Tp> template<typename _Tp>
struct common_type<_Tp> struct common_type<_Tp>
{ typedef _Tp type; }; { typedef _Tp type; };
template<typename _Tp, typename _Up> template<typename _Tp, typename _Up>
struct common_type<_Tp, _Up> struct common_type<_Tp, _Up>
{ typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; }; : public __common_type_impl<_Tp, _Up>::type
{ };
template<typename _Tp, typename _Up, typename... _Vp> template<typename _Tp, typename _Up, typename... _Vp>
struct common_type<_Tp, _Up, _Vp...> struct common_type<_Tp, _Up, _Vp...>
{ : public __expanded_common_type_wrapper<typename __member_type_wrapper<
typedef typename common_type<_Tp, _Up>>::type, _Vp...>::type
common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type; { };
};
/// The underlying type of an enum. /// The underlying type of an enum.
template<typename _Tp> template<typename _Tp>
...@@ -1818,14 +1875,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1818,14 +1875,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Signature> template<typename _Signature>
class result_of; class result_of;
// sfinae-friendly result_of implementation. We use enable_if to transport // sfinae-friendly result_of implementation:
// both the result information (as the member type) and the failure
// information (no member type).
template<typename _Tp>
using __success_type = enable_if<true, _Tp>;
using __failure_type = enable_if<false>;
// [func.require] paragraph 1 bullet 1: // [func.require] paragraph 1 bullet 1:
struct __result_of_memfun_ref_impl struct __result_of_memfun_ref_impl
......
// { dg-options "-std=c++11" }
// { dg-do compile }
// Copyright (C) 2012 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <type_traits>
#include <array>
#include <utility>
template<typename... Args>
constexpr
std::array<typename std::common_type<Args...>::type, sizeof...(Args)>
make_array(Args&&... args) // { dg-error "invalid use" }
{
typedef typename std::common_type<Args...>::type CT;
return std::array<CT, sizeof...(Args)>{static_cast<CT>
(std::forward<Args>(args))...};
}
void test01()
{
constexpr auto a1 = make_array(0);
constexpr auto a2 = make_array(0, 1.2);
constexpr auto a3 = make_array(5, true, 3.1415f, 'c');
static_assert(std::is_same<decltype(a1), const std::array<int, 1>>(), "");
static_assert(std::is_same<decltype(a2), const std::array<double, 2>>(), "");
static_assert(std::is_same<decltype(a3), const std::array<float, 4>>(), "");
}
void test02()
{
make_array(); // { dg-error "no matching function" }
}
// { dg-prune-output "substitution" }
// { dg-prune-output "include" }
// { dg-options "-std=gnu++0x" } // { dg-options "-std=gnu++0x" }
// //
// Copyright (C) 2008, 2009 Free Software Foundation, Inc. // Copyright (C) 2008-2012 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -105,7 +105,7 @@ void test02() ...@@ -105,7 +105,7 @@ void test02()
COMMON_TYPE_TEST_ALL_2(int, int, int, 1); COMMON_TYPE_TEST_ALL_2(int, int, int, 1);
COMMON_TYPE_TEST_ALL_2(int, double, double, 2); COMMON_TYPE_TEST_ALL_2(int, double, double, 2);
COMMON_TYPE_TEST_2(NO_CV, A, A, A, 3); COMMON_TYPE_TEST_2(NO_CV, A, A, A, 3);
COMMON_TYPE_TEST_2(const, A, A, const A, 4); COMMON_TYPE_TEST_2(const, A, A, A, 4);
COMMON_TYPE_TEST_2(NO_CV, B, A, A, 5); COMMON_TYPE_TEST_2(NO_CV, B, A, A, 5);
} }
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
// with this library; see the file COPYING3. If not see // with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-error "static assertion failed" "" { target *-*-* } 1812 } // { dg-error "static assertion failed" "" { target *-*-* } 1869 }
#include <utility> #include <utility>
......
// { dg-options "-std=c++11" }
// { dg-do compile }
// Copyright (C) 2012 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
#include <type_traits>
#include <chrono>
// Helper types:
struct has_type_impl
{
template<typename T, typename = typename T::type>
static std::true_type test(int);
template<typename>
static std::false_type test(...);
};
template<typename T>
struct has_type : public decltype(has_type_impl::test<T>(0))
{};
template<typename T, typename Expected>
struct is_expected_type : public std::is_same<typename T::type, Expected>
{};
template<typename P1, typename P2>
struct and_ : public std::conditional<P1::value, P2, std::false_type>::type
{};
template<typename T, typename Expected>
struct is_type : public and_<has_type<T>, is_expected_type<T, Expected>>
{};
// Inspection types:
typedef std::chrono::duration<int, std::nano> din;
typedef std::chrono::duration<double, std::nano> ddn;
typedef std::chrono::duration<int, std::milli> dim;
static_assert(is_type<std::common_type<din, din>, din>(), "");
static_assert(is_type<std::common_type<din, din, din>, din>(), "");
static_assert(is_type<std::common_type<din, ddn>, ddn>(), "");
static_assert(is_type<std::common_type<din, din, ddn>, ddn>(), "");
static_assert(is_type<std::common_type<din, ddn>, ddn>(), "");
static_assert(is_type<std::common_type<ddn, din, din>, ddn>(), "");
static_assert(!has_type<std::common_type<din, int>>(), "");
static_assert(!has_type<std::common_type<din, din, int>>(), "");
static_assert(!has_type<std::common_type<int, din, din>>(), "");
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// { dg-require-cstdint "" } // { dg-require-cstdint "" }
// 2008-07-31 Chris Fairles <chris.fairles@gmail.com> // 2008-07-31 Chris Fairles <chris.fairles@gmail.com>
// Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. // Copyright (C) 2008-2012 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -31,5 +31,5 @@ void test01() ...@@ -31,5 +31,5 @@ void test01()
test_type d; test_type d;
} }
// { dg-error "rep cannot be a duration" "" { target *-*-* } 225 } // { dg-error "rep cannot be a duration" "" { target *-*-* } 245 }
// { dg-error "required from here" "" { target *-*-* } 31 } // { dg-error "required from here" "" { target *-*-* } 31 }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// { dg-require-cstdint "" } // { dg-require-cstdint "" }
// 2008-07-31 Chris Fairles <chris.fairles@gmail.com> // 2008-07-31 Chris Fairles <chris.fairles@gmail.com>
// Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. // Copyright (C) 2008-2012 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -32,5 +32,5 @@ void test01() ...@@ -32,5 +32,5 @@ void test01()
test_type d; // { dg-error "required from here" } test_type d; // { dg-error "required from here" }
} }
// { dg-error "must be a specialization of ratio" "" { target *-*-* } 226 } // { dg-error "must be a specialization of ratio" "" { target *-*-* } 246 }
// { dg-prune-output "not a member" } // { dg-prune-output "not a member" }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// { dg-require-cstdint "" } // { dg-require-cstdint "" }
// 2008-07-31 Chris Fairles <chris.fairles@gmail.com> // 2008-07-31 Chris Fairles <chris.fairles@gmail.com>
// Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. // Copyright (C) 2008-2012 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -33,5 +33,5 @@ void test01() ...@@ -33,5 +33,5 @@ void test01()
test_type d; test_type d;
} }
// { dg-error "period must be positive" "" { target *-*-* } 228 } // { dg-error "period must be positive" "" { target *-*-* } 248 }
// { dg-error "required from here" "" { target *-*-* } 33 } // { dg-error "required from here" "" { target *-*-* } 33 }
...@@ -48,5 +48,5 @@ void test01() ...@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 } // { dg-error "required from here" "" { target *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1601 } // { dg-error "invalid use of incomplete type" "" { target *-*-* } 1613 }
// { dg-error "declaration of" "" { target *-*-* } 1565 } // { dg-error "declaration of" "" { target *-*-* } 1577 }
...@@ -48,5 +48,5 @@ void test01() ...@@ -48,5 +48,5 @@ void test01()
// { dg-error "required from here" "" { target *-*-* } 40 } // { dg-error "required from here" "" { target *-*-* } 40 }
// { dg-error "required from here" "" { target *-*-* } 42 } // { dg-error "required from here" "" { target *-*-* } 42 }
// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1519 } // { dg-error "invalid use of incomplete type" "" { target *-*-* } 1531 }
// { dg-error "declaration of" "" { target *-*-* } 1483 } // { dg-error "declaration of" "" { target *-*-* } 1495 }
...@@ -29,23 +29,27 @@ ...@@ -29,23 +29,27 @@
// Helper types: // Helper types:
struct has_type_impl struct has_type_impl
{ {
template<class T, class = typename T::type> template<typename T, typename = typename T::type>
static std::true_type test(int); static std::true_type test(int);
template<class> template<typename>
static std::false_type test(...); static std::false_type test(...);
}; };
template<class T> template<typename T>
struct has_type : decltype(has_type_impl::test<T>(0)) struct has_type : public decltype(has_type_impl::test<T>(0))
{}; {};
template<class T, class Res> template<typename T, typename Res>
struct is_expected_type : std::is_same<typename T::type, Res> struct is_expected_type : public std::is_same<typename T::type, Res>
{}; {};
template<class T, class Res> template<typename P1, typename P2>
struct is_type : std::__and_<has_type<T>, is_expected_type<T, Res>> struct and_ : public std::conditional<P1::value, P2, std::false_type>::type
{};
template<typename T, typename Res>
struct is_type : public and_<has_type<T>, is_expected_type<T, Res>>
{}; {};
// Types under inspection: // Types under inspection:
...@@ -76,18 +80,18 @@ typedef void (B::*base_func_void)() const; ...@@ -76,18 +80,18 @@ typedef void (B::*base_func_void)() const;
typedef bool (B::*base_func_bool_int)(int) const volatile; typedef bool (B::*base_func_bool_int)(int) const volatile;
struct ident_functor { struct ident_functor {
template<class T> template<typename T>
T operator()(T&& x); T operator()(T&& x);
}; };
template<class Ret = void> template<typename Ret = void>
struct variable_functor { struct variable_functor {
template<class... T> template<typename... T>
Ret operator()(T&&...); Ret operator()(T&&...);
}; };
struct ident_functor_noref { struct ident_functor_noref {
template<class T> template<typename T>
typename std::remove_reference<T>::type operator()(T&& x); typename std::remove_reference<T>::type operator()(T&& x);
}; };
...@@ -136,26 +140,26 @@ public: ...@@ -136,26 +140,26 @@ public:
bool operator()(std::nullptr_t); bool operator()(std::nullptr_t);
}; };
template<class T> template<typename T>
struct ImplicitTo { struct ImplicitTo {
operator T(); operator T();
}; };
template<class> template<typename>
struct never { static const bool value = false; }; struct never { static const bool value = false; };
template<class T> template<typename T>
struct BrokenTrait { struct BrokenTrait {
static_assert(never<T>::value, "Error!"); static_assert(never<T>::value, "Error!");
typedef T type; typedef T type;
}; };
template<class T> template<typename T>
struct BadSmartPtr : T { struct BadSmartPtr : T {
T& operator*() const noexcept(typename BrokenTrait<T>::type()); T& operator*() const noexcept(typename BrokenTrait<T>::type());
}; };
template<class Ret> template<typename Ret>
using FuncEllipses = Ret(...); using FuncEllipses = Ret(...);
static_assert(is_type<std::result_of<S(int)>, short>::value, "Error!"); static_assert(is_type<std::result_of<S(int)>, short>::value, "Error!");
......
...@@ -23,16 +23,16 @@ ...@@ -23,16 +23,16 @@
#include <type_traits> #include <type_traits>
#include <string> #include <string>
struct eat { template<class T> eat(T const &) {} }; struct eat { template<typename T> eat(T const &) {} };
struct not_incrementable {}; struct not_incrementable {};
struct inc { struct inc {
template<class T> template<typename T>
auto operator()(T t) const -> decltype(t++) auto operator()(T t) const -> decltype(t++)
{ return t++; } { return t++; }
}; };
template<class A> template<typename A>
typename std::result_of<inc(A)>::type // sfinae here typename std::result_of<inc(A)>::type // sfinae here
try_inc(A a) { try_inc(A a) {
return inc()(a); return inc()(a);
...@@ -43,10 +43,10 @@ try_inc(eat) { ...@@ -43,10 +43,10 @@ try_inc(eat) {
return not_incrementable(); return not_incrementable();
} }
template<class> template<typename>
struct never { static const bool value = false; }; struct never { static const bool value = false; };
template<class T> template<typename T>
struct Fail struct Fail
{ {
static_assert(never<T>::value, "duh"); static_assert(never<T>::value, "duh");
...@@ -55,16 +55,16 @@ struct Fail ...@@ -55,16 +55,16 @@ struct Fail
struct Fun struct Fun
{ {
template<class T> template<typename T>
typename Fail<T>::type operator()(T) typename Fail<T>::type operator()(T)
{ return 0; } { return 0; }
}; };
template<class T> template<typename T>
typename std::result_of<Fun(T)>::type foo(T) typename std::result_of<Fun(T)>::type foo(T)
{ return 0; } { return 0; }
template<class> template<typename>
int foo(...) int foo(...)
{ return 0; } { return 0; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment