Возможная реализация is_assignable

я пытаюсь привыкнуть к некоторым понятиям 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;
};

Теперь я попытался использовать некоторые другие трюки со сфинами, но это не сработало.

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)>::значение

.. Он не принимает decltype в качестве параметра шаблона в is_same.

Может ли кто-нибудь объяснить это сообщение об ошибке? и подскажите решение?

ОБНОВИТЬ:

ХОРОШО ! Оно работает ! я написал char вместо char{}....

Следующая проблема:

Есть ли более элегантная реализация?


person AF_cpp    schedule 03.07.2015    source источник
comment
std::decltype не должен компилироваться. Вы имели в виду только decltype? Кроме того, здесь нет необходимости в ключевом слове typename. Это требуется только в том случае, если у вас есть вложенное имя.   -  person dyp    schedule 03.07.2015
comment
В наши дни тенденция заключается в использовании void_t. Вы также можете наследовать от std::integral_constant или std::bool_constant (или, я думаю, Уолтер Браун унаследовал от std::is_same при реализации этого в своей презентации на CppCon) вместо того, чтобы реализовывать шаблон черты. В любом случае, вы используете зарезервированные идентификаторы. Эти имена — все, что есть у разработчиков; не усложняйте им задачу.   -  person chris    schedule 03.07.2015
comment
, char внутри decltype не является выражением. Вы, вероятно, хотите , char{}.   -  person dyp    schedule 03.07.2015
comment
Примечание: не добавляйте к своим идентификаторам префикс __ или _ + заглавную букву. Эти префиксы зарезервированы, и технически это неопределенное поведение.   -  person Anton Savin    schedule 03.07.2015
comment
вот и все -.- .. спасибо и извините . Я действительно старался изо всех сил найти ошибку :/   -  person AF_cpp    schedule 03.07.2015


Ответы (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, "!");
}
person skypjack    schedule 14.09.2016
comment
@Nik-Lz, иначе decltype дал бы нам тип T, который не является void, и поэтому шаблон класса не был бы более специализированным. См. третий параметр шаблона и его значение по умолчанию. - person skypjack; 20.09.2018
comment
Я нашел ошибку. is_assignable<int&, int>::value и is_assignable<int&, int&>::value возвращают false (и lvalue, и rvalue могут быть присвоены lvalue, std::is_assignable тоже со мной согласен). Он должен вернуть true там. - person KeyC0de; 20.09.2018
comment
@ Nik-Lz, это запятая, ты ее пропустил? - person skypjack; 20.09.2018
comment
@Nik-Lz У SO уже есть все ответы. ;-) - person skypjack; 20.09.2018

это работает для неосновных типов. Я должен представить, что с небольшой настройкой его можно заставить работать для 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;
}

ожидаемый результат:

1
0
person Richard Hodges    schedule 03.07.2015