С++/templates: Могу ли я выборочно отключить функцию класса во время компиляции?

57
4

Мне нужно написать 2 конструктора для кватернионного класса, который в основном содержит только 4 элемента численного типа T У меня есть 2 конструктора в конфликте во время компиляции (см. Ниже). Можно ли сообщить компилятору игнорировать конструктор из итератора, если я хочу вызвать конструктор, который принимает 4 ints (моя попытка закомментирована - кажется, что компилятор видит мою попытку как все или ничего, чтобы создать экземпляр всего класса). Жалоба компилятора (clang) компилятора - это "неоднозначное преобразование", и она перечисляет эти 2 конструктора при попытке выполнить Quaternion<float> x(1);

С моей пропущенной попыткой, clang говорит мне:

error: no type named 'value_type' in 'std::__1::iterator_traits<float>'
typename std::enable_if<!std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type>

Код:

template <typename T>
class Quaternion {
public:
template<typename T1>
Quaternion(T1 a = 0, T1 b = 0, T1 c = 0, T1 d = 0)
: _a(static_cast<T>(a)),
_b(static_cast<T>(b)),
_c(static_cast<T>(c)),
_d(static_cast<T>(d)) { }

template <typename It>
//typename std::enable_if<!std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type>
Quaternion(It it)
: _a(static_cast<T>(++it)),
_b(static_cast<T>(++it)),
_c(static_cast<T>(++it)),
_d(static_cast<T>(++it))
{}

private:
T _a, _b, _c, _d;
};

спросил(а) 2015-12-19T01:37:00+03:00 4 года, 9 месяцев назад
1
Решение
57

Вы можете определить пользовательский признак is_iterator:

template<typename T, typename = void>
struct is_iterator {
static bool const value = false;
};

template<typename T>
struct is_iterator<T, typename std::enable_if<!std::is_same<typename std::iterator_traits<T>::value_type, void>::value>::type> {
static bool const value = true;
};

И SFINAE внесите конструкторы с аргументом шаблона по умолчанию следующим образом:

template<typename T1, typename = typename std::enable_if<!is_iterator<T1>::value>::type>
Quaternion(T1 a = 0, T1 b = 0, T1 c = 0, T1 d = 0)
:_a(static_cast<T>(a)),
_b(static_cast<T>(b)),
_c(static_cast<T>(c)),
_d(static_cast<T>(d))
{}

template <typename It, typename = typename std::enable_if<is_iterator<It>::value>::type>
Quaternion(It it)
:_a(static_cast<T>(*(++it))),
_b(static_cast<T>(*(++it))),
_c(static_cast<T>(*(++it))),
_d(static_cast<T>(*(++it)))
{}

Демо-версия

ответил(а) 2015-12-19T02:06:00+03:00 4 года, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема