Страницы

Поиск по вопросам

понедельник, 10 июня 2019 г.

Проверка типов в конструкторе с std::forward

class A { public: using number_t = std::int32_t; using string_t = std::string;
template < class T > using vector_t = std::vector < T >;
public: template < class T1, class T2, class T3 > A(T1 && n, T2 && s, T3 && v) : m_n { std::forward < T1 > (n) }, m_s { std::forward < T2 > (s) }, m_v { std::forward < T3 > (v) } {}
private: number_t m_n; string_t m_s; vector_t < number_t > m_v; };
Вопрос: нужно ли проверять типы T1, T2, T3 в конструкторе? Я так полагаю, что нужно, потому что этот конструктор запросто съедает, например, в качестве первого аргумента double, что нежелательно. Как корректно сделать проверку? Рассматриваю вариант std::enable_if_t и std::is_same. Если так, то как удалять ссылки в случае приема конструктором lvalue-значения? Компилятор ругается на std::is_same < number_t, std::remove_reference< T1 >::type >::value. Пишет: «ожидался тип, а не вот это».


Ответ

Мне кажется, что в данном случае логично применить std::decay - типа
template,int>>, typename = enable_if_t,int>>, typename = enable_if_t,int>> > B(T1&& t1, T2&& t2, T3&& t3) : a1_{std::forward(t1)}, a2_{std::forward(t2)}, a3_{std::forward(t3)} { }
Кстати говоря,
typename = enable_if_t>>
тоже вполне работает. Причем в определенных ситуациях даже лучше - например, const int decay пропустит, убрав const, а вот remove_reference_t - уже нет, так что если, например, конструктор требует именно ссылку, а не константную ссылку - лучше remove_reference_t, если константную ссылку - лучше decay.
Словом, подгонять по месту с помощью напильника и какой-то матери... :)

Комментариев нет:

Отправить комментарий