#c #c 11 #c 14
#c #c 11 #c 14
Вопрос:
Со ссылкой на следующий код:
Я пытаюсь условно скомпилировать кучу функций, а затем «упорядочить» их с помощью prioirty_tag
class
. Мой вопрос в том, что если я заменю enable_if_t<is_nothrow_move_constructible<U>{}>* = nullptr>
на enable_if_t<is_nothrow_move_constructible<U>{}>>
, результат будет неправильным (по умолчанию используется первая функция).
Что именно там происходит? почему добавление * = nullptr
заставляет это работать?
#include <iostream>
#include <type_traits>
using namespace std;
template <size_t T>
struct priority_tag: priority_tag<T-1> {};
template <>
struct priority_tag<0> {};
template <typename T>
struct my_vec
{
template <typename U = T, typename = void>
void realloc_impl(priority_tag<0> pr)
{
cout << "Move throw constructn";
};
//template <typename U = T, enable_if_t<is_copy_constructible<U>{}>> this wont work!
template <typename U = T, enable_if_t<is_copy_constructible<U>{}>* = nullptr>
void realloc_impl(priority_tag<1> pr)
{
cout << "copy construct n";
};
//template <typename U = T, enable_if_t<is_copy_constructible<U>{}>> this wont work!
template <typename U = T, enable_if_t<is_nothrow_move_constructible<U>{}>* = nullptr>
void realloc_impl(priority_tag<2> pr)
{
cout << "nothrow move n";
};
void realloc()
{
priority_tag<2> pr;
realloc_impl(pr);
}
const static int val = is_nothrow_move_constructible<T>{} ? 1 : is_copy_constructible<T>{} ? 2 : 3;
priority_tag<val> g;
};
class A {
public:
A() = default;
A(Aamp;amp;) noexcept = default;
};
class B {
public:
B() = default;
B(Bamp;amp;) = delete;
B(const Bamp;) = default;
};
class C {
public:
C() = default;
C(Camp;amp;) {}
C(const Camp;) = delete;
};
int main()
{
my_vec<A> obj;
obj.realloc();
cout << obj.val;
}
Ответ №1:
Попробуйте скомпилировать приведенный ниже код
template<void>
void foo(){}
Я получил ошибку компилятора ‘void’ не является допустимым типом для параметра, отличного от типа шаблона.
В качестве параметра шаблона вы можете передать:
1) введите, затем вы объявляете его, используя class / typename, как показано ниже:
template< class/typename A[optional] = void>
void foo2(){}
2) нетипизированный
затем вы можете передать в качестве параметра шаблона некоторое промежуточное значение, указатели, ссылку на значение Lvalue и т.д. (полный список здесь)
template<void*>
void foo3(){}
3) параметр типа шаблона
В вашем примере is_nothrow_move_constructible
возвращает true для A
, затем компилятор встречает строку:
template <typename U = T, enable_if_t<is_nothrow_move_constructible<U>{}>>
что такое:
template <typename U = T, void>
эта строка имеет неправильный синтаксис, и компилятор удаляет этот шаблон функции-члена из набора перегрузок.
Вы можете исправить это, объявив enable_if_t<is_nothrow_move_constructible<U>{}
в качестве параметра типа:
template <typename U = T,
typename = enable_if_t<is_nothrow_move_constructible<U>{}> > // typename = void
void realloc_impl(priority_tag<2> pr)
{
cout << "nothrow move n";
};
или как нетип (указатель на void), что вы сделали в своем примере.
Комментарии:
1. Спасибо! Это имеет смысл