Имея эту функцию:

template <typename T>
T operator-(const T vector)
{}

Я хочу обеспечить, чтобы у T были члены x и y, и что они являются арифметическими. Я пытался сделать это через std::declval<T>:

template <typename T,
  typename = typename 
    std::enable_if<std::is_arithmetic<std::declval<T>.x>::value>::type,
  typename = typename 
    std::enable_if<std::is_arithmetic<std::declval<T>.y>::value>::type>
T operator-(const T vector)
{}

Но все, что я получаю, это то, что тип не может быть выведен: error: insufficient contextual information to determine type . Можно ли вообще определить тип члена объекта параметра шаблона?

3
sjaustirni 24 Фев 2016 в 18:52
1
Синтаксис std::declval<T>.x можно использовать только с объектом, но не с типом.
 – 
R Sahu
24 Фев 2016 в 19:18
@RSahu: Верно. Я этого не заметил. Спасибо. Возможно ли тогда каким-либо образом узнать тип члена переданного объекта во время компиляции?
 – 
sjaustirni
24 Фев 2016 в 19:21
Я пытался использовать std::is_arithmetic<typename T::x>::value, он компилируется, но, похоже, не работает.
 – 
sjaustirni
24 Фев 2016 в 19:25
3
decltype(std::declval<T>().x) или decltype(T::x).
 – 
T.C.
24 Фев 2016 в 19:42
2
@ T.C. Последнее может непреднамеренно давать ложноотрицательные результаты для классов C ++ 17 с перегруженной точкой оператора. : o)
 – 
Columbo
24 Фев 2016 в 19:55

1 ответ

Лучший ответ

Я так понимаю, вы на самом деле не хотите, чтобы они были арифметическими. Вы хотите, чтобы ключевые выражения в теле шаблона функции были правильно сформированы. В этом случае сделайте что-нибудь вроде

template <typename T>
auto operator-(const T& vector)
  -> decltype(void(x - vector.x), void(y - vector.y), vector)
{/* ... */}

Если вы предпочитаете использовать правильную версию кода, достаточно заменить std::declval<T>.x std::declval<T>.x на decltype(std::declval<T>().x) или decltype(T::x) (то же самое для y):

template <typename T,
  typename = std::enable_if_t<std::is_arithmetic<decltype(T::x)>{}>,
  typename = std::enable_if_t<std::is_arithmetic<decltype(T::x)>{}>>
T operator-(const T vector)
{}
3
Columbo 24 Фев 2016 в 20:28
Я действительно хочу убедиться, что они арифметичны. Мне нужно отрицать их ценности. Это не имеет смысла, если они не арифметичны. Или мне что-то здесь не хватает?
 – 
sjaustirni
24 Фев 2016 в 19:58
@Dundee: комплексные / рациональные числа не являются арифметикой , но отрицать их имеет смысл.
 – 
Jarod42
24 Фев 2016 в 20:10
Унарный оператор - может быть перегружен.
 – 
Columbo
24 Фев 2016 в 20:10
@ Jarod42: Вы правы. К счастью, они не подходят для моего случая использования.
 – 
sjaustirni
24 Фев 2016 в 20:18
@Columbo: Да, я знаю. Это больше связано с тем, как я хочу использовать библиотеку. В любом случае, спасибо за оба варианта. Ты удивительный :)
 – 
sjaustirni
24 Фев 2016 в 20:19