is_assignable

时间:2015-07-03 12:47:46

标签: c++ sfinae tmp

我正在尝试习惯一些tmp概念。

这是一个检查2种类型是否可分配的解决方案: 这是最重要的部分:

template<typename _Tp, typename _Up>
class __is_assignable_helper: public __sfinae_types {

template<typename _Tp1, typename _Up1>
static decltype(std::declval<_Tp1>() = std::declval<_Up1>(), __one())
__test(int) {}

template<typename, typename>
static __two __test(...) {}

public:
static constexpr bool value = sizeof(__test<_Tp, _Up>(0)) == 1;
};

现在我尝试使用其他一些sfinae技巧,但它不起作用..

template<typename _Tp, typename _Up, typename = void>
class __is_assignable_helper2
{

public:
static constexpr bool value = false;
};


template<typename _Tp, typename _Up>
class __is_assignable_helper2<_Tp, _Up, 
                                typename std::enable_if<
                                std::is_same<typename
                                decltype(std::declval<_Tp>()=    std::declval<_Up>(), char)
,char >::value
                                                                     , void
                                                        >::type>
{

public:
 static constexpr bool value = true;
};

GCC说:错误:模板参数数量错误(1,应为2)&gt; :: value

..他不接受is_same中的decltype作为模板参数。

有人可以解释此错误消息吗?并建议一个解决方案?

更新:

好的!有用 !我写了char,而不是char {} ....

下一个问题:

是否有更优雅的实施?

2 个答案:

答案 0 :(得分:2)

这是一个可能的实现:

#include<type_traits>
#include<string>

template<typename T, typename U, typename = void>
struct is_assignable: std::false_type {};

template<typename T, typename U>
struct is_assignable<T, U, decltype(std::declval<T>() = std::declval<U>(), void())>: std::true_type {};

int main() {
    static_assert(is_assignable<std::string, const char*>::value, "!");
    static_assert(not is_assignable<const char*, std::string>::value, "!");
    static_assert(is_assignable<int &, int &>::value, "!");
}

答案 1 :(得分:0)

这适用于非基本类型。我应该想象一下,通过一些调整,它可以用于[UNION][1]次转换等。

int = long

预期产出:

#include <iostream>
#include <utility>
#include <string>

// fallback helper for when the true case won't compile - returns false_type
template<class T, class From>
std::false_type is_assignable_impl(...) { return {}; }

// this overload preferred if decltype(T = From) yields a type   
// returns a true_type
template<class T, class From>
auto
is_assignable_impl(int)
-> decltype(std::declval<T>() = std::declval<From>(), void(), std::true_type())
{ return {}; }

// derived from either false_type or true_type    
template<class T, class From>
struct my_assignable : decltype(is_assignable_impl<T, From>(0)) {};

// a test...
using namespace std;

auto main() -> int
{
    cout << my_assignable<std::string, const char*>::value << endl;
    cout << my_assignable<const char*, std::string>::value << endl;

    return 0;
}