Сбой при выводе типа аргумента шаблона с C ++ 11 & lt; type_traits & gt;

Я пытаюсь понять, как использовать C ++ (11) <type_traits>,

Вот моя тривиальная тестовая программа

#include <type_traits>

template<class U, class S>
inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a,
typename std::enable_if<std::is_signed  <S>::value,S>::type b)
{
return a + b;
}

int main(int argc, const char * argv[], const char * envp[])
{
unsigned int ui;
int i;
auto a = add(ui, i);
return 0;
}

При компиляции с GCC 4.8.1 это ошибки как

/home/per/f.cpp: In function ‘int main(int, const char**, const char**)’:
/home/per/f.cpp:15:23: error: no matching function for call to ‘add(unsigned int&, int&)’
auto a = add(ui, i);
^
/home/per/f.cpp:15:23: note: candidate is:
/home/per/f.cpp:5:10: note: template<class U, class S> U add(typename std::enable_if<std::is_unsigned<U>::value, U>::type, typename std::enable_if<std::is_signed<S>::value, S>::type)
inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a,
^
/home/per/f.cpp:5:10: note:   template argument deduction/substitution failed:
/home/per/f.cpp:15:23: note:   couldn't deduce template parameter ‘U’
auto a = add(ui, i);
^

Я понятия не имею, почему GCC не может определить параметр шаблона U, Кто-нибудь знает, какая информация отсутствует в моем коде, то есть как я пишу программу на C ++ 11, которая принимает целочисленный тип без знака в качестве первого аргумента и целочисленный тип со знаком в качестве второго?

7

Решение

typename std::enable_if<std::is_unsigned<U>::value,U>::type не выводимый контекст. Для того, чтобы вывести U Исходя из этого, компилятору потребуется возможность применить обратную операцию std::enable_if, Это не выглядит слишком сложно, это правда, но это потому, что вы говорите о такой простой вещи, как enable_if, Было бы невозможно требовать этого для каждой черты, поэтому C ++ просто играет круто и не делает никаких странных исключений из правил: это вообще не выводимо, в этом не выводимо.

Вы можете сделать это следующим образом:

template<class U, class S,
EnableIf<std::is_unsigned<U>, std::is_signed<S>>...>
// see http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html
U add(U a, S b)

Или в компиляторах, которые не поддерживают этот стиль должным образом, вы можете просто добавить дополнительный аргумент по умолчанию:

template<class U, class S>
U add(U a, S b,
typename std::enable_if<std::is_unsigned<U>::value
&& std::is_signed<S>::value,void>::type* = nullptr)

… или возиться с типом возврата.

template<class U, class S>
typename std::enable_if<std::is_unsigned<U>::value
&& std::is_signed<S>::value,U>::type
add(U a, S b)
13

Другие решения

Вы не даете компилятору шанс вывести U а также S, Вы можете переписать свою функцию следующим образом и переместить проверки SFINAE в список параметров шаблона:

template<class U, class S,
typename std::enable_if<std::is_unsigned<U>::value &&
std::is_signed  <S>::value
>::type* = nullptr>
inline U add(U a, S b)
{
return a + b;
}

Вот живой пример.

7

Сначала вы должны определить типы до Вы можете рассуждать о типах!

Так должно быть:

template <typename U, typename S>
typename std::enable_if<std::is_unsigned<U>::value &&
std::is_signed<S>::value>, U>::type
add(U u, S s)
{
// ...
}
3

Невозможно вывести параметр шаблона из выражения «вложенный typedef». То есть можно вывести U от some_template<U>, но не из some_template<U>::type,

Компилятор не может перечислять все (бесконечные!) Экземпляры some_template и посмотрите, для какого из них вложенная typedef равна фактическому типу аргумента.

2

Пытаться:

template<class U, class S>
typename std::enable_if<std::is_unsigned<U>::value && std::is_signed<S>,U>::type
add(U a , S b)
{
return a + b;
}
2
По вопросам рекламы [email protected]