You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
642 lines
19 KiB
642 lines
19 KiB
11 years ago
|
/*
|
||
|
* Copyright 2008-2012 NVIDIA Corporation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*! \file type_traits.h
|
||
|
* \brief Temporarily define some type traits
|
||
|
* until nvcc can compile tr1::type_traits.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <thrust/detail/config.h>
|
||
|
|
||
|
// XXX nvcc 2.2 closed beta can't compile type_traits
|
||
|
//// find type_traits
|
||
|
//
|
||
|
//#ifdef __GNUC__
|
||
|
//
|
||
|
//#if __GNUC__ == 4 && __GNUC_MINOR__ == 2
|
||
|
//#include <tr1/type_traits>
|
||
|
//#elif __GNUC__ == 4 && __GNUC_MINOR__ > 2
|
||
|
//#include <type_traits>
|
||
|
//#endif // GCC version
|
||
|
//
|
||
|
//#endif // GCC
|
||
|
//
|
||
|
//#ifdef _MSC_VER
|
||
|
//#include <type_traits>
|
||
|
//#endif // MSVC
|
||
|
|
||
|
|
||
|
namespace thrust
|
||
|
{
|
||
|
|
||
|
// forward declaration of device_reference
|
||
|
template<typename T> class device_reference;
|
||
|
|
||
|
namespace detail
|
||
|
{
|
||
|
/// helper classes [4.3].
|
||
|
template<typename _Tp, _Tp __v>
|
||
|
struct integral_constant
|
||
|
{
|
||
|
static const _Tp value = __v;
|
||
|
typedef _Tp value_type;
|
||
|
typedef integral_constant<_Tp, __v> type;
|
||
|
};
|
||
|
|
||
|
/// typedef for true_type
|
||
|
typedef integral_constant<bool, true> true_type;
|
||
|
|
||
|
/// typedef for true_type
|
||
|
typedef integral_constant<bool, false> false_type;
|
||
|
|
||
|
//template<typename T> struct is_integral : public std::tr1::is_integral<T> {};
|
||
|
template<typename T> struct is_integral : public false_type {};
|
||
|
template<> struct is_integral<bool> : public true_type {};
|
||
|
template<> struct is_integral<char> : public true_type {};
|
||
|
template<> struct is_integral<signed char> : public true_type {};
|
||
|
template<> struct is_integral<unsigned char> : public true_type {};
|
||
|
template<> struct is_integral<short> : public true_type {};
|
||
|
template<> struct is_integral<unsigned short> : public true_type {};
|
||
|
template<> struct is_integral<int> : public true_type {};
|
||
|
template<> struct is_integral<unsigned int> : public true_type {};
|
||
|
template<> struct is_integral<long> : public true_type {};
|
||
|
template<> struct is_integral<unsigned long> : public true_type {};
|
||
|
template<> struct is_integral<long long> : public true_type {};
|
||
|
template<> struct is_integral<unsigned long long> : public true_type {};
|
||
|
template<> struct is_integral<const bool> : public true_type {};
|
||
|
template<> struct is_integral<const char> : public true_type {};
|
||
|
template<> struct is_integral<const unsigned char> : public true_type {};
|
||
|
template<> struct is_integral<const short> : public true_type {};
|
||
|
template<> struct is_integral<const unsigned short> : public true_type {};
|
||
|
template<> struct is_integral<const int> : public true_type {};
|
||
|
template<> struct is_integral<const unsigned int> : public true_type {};
|
||
|
template<> struct is_integral<const long> : public true_type {};
|
||
|
template<> struct is_integral<const unsigned long> : public true_type {};
|
||
|
template<> struct is_integral<const long long> : public true_type {};
|
||
|
template<> struct is_integral<const unsigned long long> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_floating_point : public false_type {};
|
||
|
template<> struct is_floating_point<float> : public true_type {};
|
||
|
template<> struct is_floating_point<double> : public true_type {};
|
||
|
template<> struct is_floating_point<long double> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_arithmetic : public is_integral<T> {};
|
||
|
template<> struct is_arithmetic<float> : public true_type {};
|
||
|
template<> struct is_arithmetic<double> : public true_type {};
|
||
|
template<> struct is_arithmetic<const float> : public true_type {};
|
||
|
template<> struct is_arithmetic<const double> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_pointer : public false_type {};
|
||
|
template<typename T> struct is_pointer<T *> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_device_ptr : public false_type {};
|
||
|
|
||
|
template<typename T> struct is_void : public false_type {};
|
||
|
template<> struct is_void<void> : public true_type {};
|
||
|
template<> struct is_void<const void> : public true_type {};
|
||
|
|
||
|
|
||
|
namespace tt_detail
|
||
|
{
|
||
|
|
||
|
|
||
|
} // end tt_detail
|
||
|
|
||
|
template<typename T> struct is_pod
|
||
|
: public integral_constant<
|
||
|
bool,
|
||
|
is_void<T>::value || is_pointer<T>::value || is_arithmetic<T>::value
|
||
|
#if THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_MSVC
|
||
|
// use intrinsic type traits
|
||
|
|| __is_pod(T)
|
||
|
#elif THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_GCC
|
||
|
// only use the intrinsic for >= 4.3
|
||
|
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
|
||
|
|| __is_pod(T)
|
||
|
#endif // GCC VERSION
|
||
|
#endif // THRUST_HOST_COMPILER
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename T> struct has_trivial_constructor
|
||
|
: public integral_constant<
|
||
|
bool,
|
||
|
is_pod<T>::value
|
||
|
#if THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_MSVC
|
||
|
|| __has_trivial_constructor(T)
|
||
|
#elif THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_GCC
|
||
|
// only use the intrinsic for >= 4.3
|
||
|
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
|
||
|
|| __has_trivial_constructor(T)
|
||
|
#endif // GCC VERSION
|
||
|
#endif // THRUST_HOST_COMPILER
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
template<typename T> struct has_trivial_copy_constructor
|
||
|
: public integral_constant<
|
||
|
bool,
|
||
|
is_pod<T>::value
|
||
|
#if THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_MSVC
|
||
|
|| __has_trivial_copy(T)
|
||
|
#elif THRUST_HOST_COMPILER == THRUST_HOST_COMPILER_GCC
|
||
|
// only use the intrinsic for >= 4.3
|
||
|
#if (__GNUC__ >= 4) && (__GNUC_MINOR__ >= 3)
|
||
|
|| __has_trivial_copy(T)
|
||
|
#endif // GCC VERSION
|
||
|
#endif // THRUST_HOST_COMPILER
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
template<typename T> struct has_trivial_destructor : public is_pod<T> {};
|
||
|
|
||
|
template<typename T> struct is_const : public false_type {};
|
||
|
template<typename T> struct is_const<const T> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_volatile : public false_type {};
|
||
|
template<typename T> struct is_volatile<volatile T> : public true_type {};
|
||
|
|
||
|
template<typename T>
|
||
|
struct add_const
|
||
|
{
|
||
|
typedef T const type;
|
||
|
}; // end add_const
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_const
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_const
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_const<const T>
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_const
|
||
|
|
||
|
template<typename T>
|
||
|
struct add_volatile
|
||
|
{
|
||
|
typedef volatile T type;
|
||
|
}; // end add_volatile
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_volatile
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_volatile
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_volatile<volatile T>
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_volatile
|
||
|
|
||
|
template<typename T>
|
||
|
struct add_cv
|
||
|
{
|
||
|
typedef const volatile T type;
|
||
|
}; // end add_cv
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_cv
|
||
|
{
|
||
|
typedef typename remove_const<typename remove_volatile<T>::type>::type type;
|
||
|
}; // end remove_cv
|
||
|
|
||
|
|
||
|
template<typename T> struct is_reference : public false_type {};
|
||
|
template<typename T> struct is_reference<T&> : public true_type {};
|
||
|
|
||
|
template<typename T> struct is_device_reference : public false_type {};
|
||
|
template<typename T> struct is_device_reference< thrust::device_reference<T> > : public true_type {};
|
||
|
|
||
|
|
||
|
// NB: Careful with reference to void.
|
||
|
template<typename _Tp, bool = (is_void<_Tp>::value || is_reference<_Tp>::value)>
|
||
|
struct __add_reference_helper
|
||
|
{ typedef _Tp& type; };
|
||
|
|
||
|
template<typename _Tp>
|
||
|
struct __add_reference_helper<_Tp, true>
|
||
|
{ typedef _Tp type; };
|
||
|
|
||
|
template<typename _Tp>
|
||
|
struct add_reference
|
||
|
: public __add_reference_helper<_Tp>{};
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_reference
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_reference
|
||
|
|
||
|
template<typename T>
|
||
|
struct remove_reference<T&>
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end remove_reference
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct is_same
|
||
|
: public false_type
|
||
|
{
|
||
|
}; // end is_same
|
||
|
|
||
|
template<typename T>
|
||
|
struct is_same<T,T>
|
||
|
: public true_type
|
||
|
{
|
||
|
}; // end is_same
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct lazy_is_same
|
||
|
: is_same<typename T1::type, typename T2::type>
|
||
|
{
|
||
|
}; // end lazy_is_same
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct is_different
|
||
|
: public true_type
|
||
|
{
|
||
|
}; // end is_different
|
||
|
|
||
|
template<typename T>
|
||
|
struct is_different<T,T>
|
||
|
: public false_type
|
||
|
{
|
||
|
}; // end is_different
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct lazy_is_different
|
||
|
: is_different<typename T1::type, typename T2::type>
|
||
|
{
|
||
|
}; // end lazy_is_different
|
||
|
|
||
|
namespace tt_detail
|
||
|
{
|
||
|
|
||
|
template<typename T>
|
||
|
struct is_int_or_cref
|
||
|
{
|
||
|
typedef typename remove_reference<T>::type type_sans_ref;
|
||
|
static const bool value = (is_integral<T>::value
|
||
|
|| (is_integral<type_sans_ref>::value
|
||
|
&& is_const<type_sans_ref>::value
|
||
|
&& !is_volatile<type_sans_ref>::value));
|
||
|
}; // end is_int_or_cref
|
||
|
|
||
|
|
||
|
__THRUST_DISABLE_MSVC_POSSIBLE_LOSS_OF_DATA_WARNING_BEGIN
|
||
|
__THRUST_DISABLE_MSVC_FORCING_VALUE_TO_BOOL_BEGIN
|
||
|
|
||
|
|
||
|
template<typename From, typename To>
|
||
|
struct is_convertible_sfinae
|
||
|
{
|
||
|
private:
|
||
|
typedef char one_byte;
|
||
|
typedef struct { char two_chars[2]; } two_bytes;
|
||
|
|
||
|
static one_byte test(To);
|
||
|
static two_bytes test(...);
|
||
|
static From m_from;
|
||
|
|
||
|
public:
|
||
|
static const bool value = sizeof(test(m_from)) == sizeof(one_byte);
|
||
|
}; // end is_convertible_sfinae
|
||
|
|
||
|
|
||
|
__THRUST_DISABLE_MSVC_FORCING_VALUE_TO_BOOL_END
|
||
|
__THRUST_DISABLE_MSVC_POSSIBLE_LOSS_OF_DATA_WARNING_END
|
||
|
|
||
|
|
||
|
template<typename From, typename To>
|
||
|
struct is_convertible_needs_simple_test
|
||
|
{
|
||
|
static const bool from_is_void = is_void<From>::value;
|
||
|
static const bool to_is_void = is_void<To>::value;
|
||
|
static const bool from_is_float = is_floating_point<typename remove_reference<From>::type>::value;
|
||
|
static const bool to_is_int_or_cref = is_int_or_cref<To>::value;
|
||
|
|
||
|
static const bool value = (from_is_void || to_is_void || (from_is_float && to_is_int_or_cref));
|
||
|
}; // end is_convertible_needs_simple_test
|
||
|
|
||
|
|
||
|
template<typename From, typename To,
|
||
|
bool = is_convertible_needs_simple_test<From,To>::value>
|
||
|
struct is_convertible
|
||
|
{
|
||
|
static const bool value = (is_void<To>::value
|
||
|
|| (is_int_or_cref<To>::value
|
||
|
&& !is_void<From>::value));
|
||
|
}; // end is_convertible
|
||
|
|
||
|
|
||
|
template<typename From, typename To>
|
||
|
struct is_convertible<From, To, false>
|
||
|
{
|
||
|
static const bool value = (is_convertible_sfinae<typename
|
||
|
add_reference<From>::type, To>::value);
|
||
|
}; // end is_convertible
|
||
|
|
||
|
|
||
|
} // end tt_detail
|
||
|
|
||
|
template<typename From, typename To>
|
||
|
struct is_convertible
|
||
|
: public integral_constant<bool, tt_detail::is_convertible<From, To>::value>
|
||
|
{
|
||
|
}; // end is_convertible
|
||
|
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct is_one_convertible_to_the_other
|
||
|
: public integral_constant<
|
||
|
bool,
|
||
|
is_convertible<T1,T2>::value || is_convertible<T2,T1>::value
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
// mpl stuff
|
||
|
|
||
|
template <typename Condition1, typename Condition2, typename Condition3 = false_type,
|
||
|
typename Condition4 = false_type, typename Condition5 = false_type, typename Condition6 = false_type,
|
||
|
typename Condition7 = false_type, typename Condition8 = false_type, typename Condition9 = false_type,
|
||
|
typename Condition10 = false_type>
|
||
|
struct or_
|
||
|
: public integral_constant<
|
||
|
bool,
|
||
|
Condition1::value || Condition2::value || Condition3::value || Condition4::value || Condition5::value || Condition6::value || Condition7::value || Condition8::value || Condition9::value || Condition10::value
|
||
|
>
|
||
|
{
|
||
|
}; // end or_
|
||
|
|
||
|
template <typename Condition1, typename Condition2, typename Condition3 = true_type>
|
||
|
struct and_
|
||
|
: public integral_constant<bool, Condition1::value && Condition2::value && Condition3::value>
|
||
|
{
|
||
|
}; // end and_
|
||
|
|
||
|
template <typename Boolean>
|
||
|
struct not_
|
||
|
: public integral_constant<bool, !Boolean::value>
|
||
|
{
|
||
|
}; // end not_
|
||
|
|
||
|
template <bool, typename Then, typename Else>
|
||
|
struct eval_if
|
||
|
{
|
||
|
}; // end eval_if
|
||
|
|
||
|
template<typename Then, typename Else>
|
||
|
struct eval_if<true, Then, Else>
|
||
|
{
|
||
|
typedef typename Then::type type;
|
||
|
}; // end eval_if
|
||
|
|
||
|
template<typename Then, typename Else>
|
||
|
struct eval_if<false, Then, Else>
|
||
|
{
|
||
|
typedef typename Else::type type;
|
||
|
}; // end eval_if
|
||
|
|
||
|
template<typename T>
|
||
|
// struct identity
|
||
|
// XXX WAR nvcc's confusion with thrust::identity
|
||
|
struct identity_
|
||
|
{
|
||
|
typedef T type;
|
||
|
}; // end identity
|
||
|
|
||
|
template<bool, typename T = void> struct enable_if {};
|
||
|
template<typename T> struct enable_if<true, T> {typedef T type;};
|
||
|
|
||
|
template<bool, typename T> struct lazy_enable_if {};
|
||
|
template<typename T> struct lazy_enable_if<true, T> {typedef typename T::type type;};
|
||
|
|
||
|
template<bool condition, typename T = void> struct disable_if : enable_if<!condition, T> {};
|
||
|
template<bool condition, typename T> struct lazy_disable_if : lazy_enable_if<!condition, T> {};
|
||
|
|
||
|
|
||
|
template<typename T1, typename T2, typename T = void>
|
||
|
struct enable_if_convertible
|
||
|
: enable_if< is_convertible<T1,T2>::value, T >
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename T1, typename T2, typename T = void>
|
||
|
struct disable_if_convertible
|
||
|
: disable_if< is_convertible<T1,T2>::value, T >
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename T1, typename T2, typename Result = void>
|
||
|
struct enable_if_different
|
||
|
: enable_if<is_different<T1,T2>::value, Result>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename T>
|
||
|
struct is_numeric
|
||
|
: and_<
|
||
|
is_convertible<int,T>,
|
||
|
is_convertible<T,int>
|
||
|
>
|
||
|
{
|
||
|
}; // end is_numeric
|
||
|
|
||
|
|
||
|
template<typename> struct is_reference_to_const : false_type {};
|
||
|
template<typename T> struct is_reference_to_const<const T&> : true_type {};
|
||
|
|
||
|
|
||
|
// make_unsigned follows
|
||
|
|
||
|
namespace tt_detail
|
||
|
{
|
||
|
|
||
|
template<typename T> struct make_unsigned_simple;
|
||
|
|
||
|
template<> struct make_unsigned_simple<char> { typedef unsigned char type; };
|
||
|
template<> struct make_unsigned_simple<signed char> { typedef signed char type; };
|
||
|
template<> struct make_unsigned_simple<unsigned char> { typedef unsigned char type; };
|
||
|
template<> struct make_unsigned_simple<short> { typedef unsigned short type; };
|
||
|
template<> struct make_unsigned_simple<unsigned short> { typedef unsigned short type; };
|
||
|
template<> struct make_unsigned_simple<int> { typedef unsigned int type; };
|
||
|
template<> struct make_unsigned_simple<unsigned int> { typedef unsigned int type; };
|
||
|
template<> struct make_unsigned_simple<long int> { typedef unsigned long int type; };
|
||
|
template<> struct make_unsigned_simple<unsigned long int> { typedef unsigned long int type; };
|
||
|
template<> struct make_unsigned_simple<long long int> { typedef unsigned long long int type; };
|
||
|
template<> struct make_unsigned_simple<unsigned long long int> { typedef unsigned long long int type; };
|
||
|
|
||
|
template<typename T>
|
||
|
struct make_unsigned_base
|
||
|
{
|
||
|
// remove cv
|
||
|
typedef typename remove_cv<T>::type remove_cv_t;
|
||
|
|
||
|
// get the simple unsigned type
|
||
|
typedef typename make_unsigned_simple<remove_cv_t>::type unsigned_remove_cv_t;
|
||
|
|
||
|
// add back const, volatile, both, or neither to the simple result
|
||
|
typedef typename eval_if<
|
||
|
is_const<T>::value && is_volatile<T>::value,
|
||
|
// add cv back
|
||
|
add_cv<unsigned_remove_cv_t>,
|
||
|
// check const & volatile individually
|
||
|
eval_if<
|
||
|
is_const<T>::value,
|
||
|
// add c back
|
||
|
add_const<unsigned_remove_cv_t>,
|
||
|
eval_if<
|
||
|
is_volatile<T>::value,
|
||
|
// add v back
|
||
|
add_volatile<unsigned_remove_cv_t>,
|
||
|
// original type was neither cv, return the simple unsigned result
|
||
|
identity_<unsigned_remove_cv_t>
|
||
|
>
|
||
|
>
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
} // end tt_detail
|
||
|
|
||
|
template<typename T>
|
||
|
struct make_unsigned
|
||
|
: tt_detail::make_unsigned_base<T>
|
||
|
{};
|
||
|
|
||
|
struct largest_available_float
|
||
|
{
|
||
|
#if defined(__CUDA_ARCH__)
|
||
|
# if (__CUDA_ARCH__ < 130)
|
||
|
typedef float type;
|
||
|
# else
|
||
|
typedef double type;
|
||
|
# endif
|
||
|
#else
|
||
|
typedef double type;
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
// T1 wins if they are both the same size
|
||
|
template<typename T1, typename T2>
|
||
|
struct larger_type
|
||
|
: thrust::detail::eval_if<
|
||
|
(sizeof(T2) > sizeof(T1)),
|
||
|
thrust::detail::identity_<T2>,
|
||
|
thrust::detail::identity_<T1>
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
namespace is_base_of_ns
|
||
|
{
|
||
|
|
||
|
typedef char yes;
|
||
|
typedef struct { char two_chars[2]; } no;
|
||
|
|
||
|
template<typename Base, typename Derived>
|
||
|
struct host
|
||
|
{
|
||
|
operator Base*() const;
|
||
|
operator Derived*();
|
||
|
}; // end host
|
||
|
|
||
|
template<typename Base, typename Derived>
|
||
|
struct impl
|
||
|
{
|
||
|
template<typename T> static yes check(Derived *, T);
|
||
|
static no check(Base*, int);
|
||
|
|
||
|
static const bool value = sizeof(check(host<Base,Derived>(), int())) == sizeof(yes);
|
||
|
}; // end impl
|
||
|
|
||
|
} // end is_base_of_ns
|
||
|
|
||
|
|
||
|
template<typename Base, typename Derived>
|
||
|
struct is_base_of
|
||
|
: integral_constant<
|
||
|
bool,
|
||
|
is_base_of_ns::impl<Base,Derived>::value
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
template<typename Base, typename Derived, typename Result = void>
|
||
|
struct enable_if_base_of
|
||
|
: enable_if<
|
||
|
is_base_of<Base,Derived>::value,
|
||
|
Result
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
namespace is_assignable_ns
|
||
|
{
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
class is_assignable
|
||
|
{
|
||
|
typedef char yes_type;
|
||
|
typedef struct { char array[2]; } no_type;
|
||
|
|
||
|
template<typename T> static typename add_reference<T>::type declval();
|
||
|
|
||
|
template<unsigned int> struct helper { typedef void * type; };
|
||
|
|
||
|
template<typename U1, typename U2> static yes_type test(typename helper<sizeof(declval<U1>() = declval<U2>())>::type);
|
||
|
|
||
|
template<typename,typename> static no_type test(...);
|
||
|
|
||
|
public:
|
||
|
static const bool value = sizeof(test<T1,T2>(0)) == 1;
|
||
|
}; // end is_assignable
|
||
|
|
||
|
} // end is_assignable_ns
|
||
|
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct is_assignable
|
||
|
: integral_constant<
|
||
|
bool,
|
||
|
is_assignable_ns::is_assignable<T1,T2>::value
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename T>
|
||
|
struct is_copy_assignable
|
||
|
: is_assignable<
|
||
|
typename add_reference<T>::type,
|
||
|
typename add_reference<typename add_const<T>::type>::type
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
} // end detail
|
||
|
|
||
|
} // end thrust
|
||
|
|
||
|
#include <thrust/detail/type_traits/has_trivial_assign.h>
|
||
|
|