Ошибка «Нет совпадения» после введения std :: enable_if - PullRequest
2 голосов
/ 25 марта 2019

У меня есть оператор (в данном случае operator&=, но это не проблема), который прекрасно работает, пока я не введу std::enable_if_t в микс.

Проще объяснить на примере кода:

template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>>>
MyClass& MyClass::operator&=(T d)
{ /*... */ }

// then in main
MyClass a;
a &= static_cast<unsigned char>42;
a &= (unsigned long long)47;

Если я закомментирую блок std::enable_if_t, он компилируется и запускается, как и ожидалось, но как только я помещаю его туда, он выдает ошибки в формате

test.cpp:42:7: error: no match for ‘operator&=’ (operand types are ‘MyClass’ and ‘unsigned char’)
  a &= static_cast<unsigned char>(42);
  ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from test.cpp:4:0:
file.hpp:69:103: note: candidate: template<class T, typename std::enable_if<(is_integral_v<T> && is_unsigned_v<T>), void>::type <anonymous> > MyClass& MyClass::operator&=(T)
  template<typename T, std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>>> MyClass& operator&=(T d);
                                                                                                  ^~~~~~~~
file.hpp:69:103: note:   template argument deduction/substitution failed:
test.cpp:42:39: note:   couldn't deduce template parameter ‘<anonymous>’
  a &= static_cast<unsigned char>(42);

Я чувствую, что мне здесь не хватает чего-то простого. Я даже пытался намекнуть компилятору, вызвав a.operator&=<unsigned char>(static_cast<unsigned char>(42)), чтобы посмотреть, будет ли он работать, но это не так.

1 Ответ

3 голосов
/ 25 марта 2019

Вам необходимо использовать class / typename во втором параметре шаблона в определении

template<typename T, class = std::enable_if_t<std::is_integral_v<T> && std::is_unsigned_v<T>>>
                     ^^^^^
MyClass& MyClass::operator&=(T d)

Когда условие std::is_integral_v<T> && std::is_unsigned_v<T> истинно, enable_if::type равно void.Без class void обрабатывается как нетипичный параметр шаблона, что является неправильным (void не может использоваться как нетипичный параметр ссылка ).

При использовании class/ typename второй параметр определен как параметр типа, который принимает значение void - class SomeTypeName = void, если условие в enable_if имеет значение true, или этот шаблон функции отбрасывается из перегрузок, установленных, когда условие enable_if имеет значение false.

...