Я хочу реализовать признак типа has_no_duplicates<...>
, который оценивается как std::true_type
, если в переданном списке вариационного типа нет повторяющихся типов.Использование `void_t` для обнаружения множественных ошибок повторения типа наследования
static_assert(has_no_duplicates<int, float>{}, "");
static_assert(!has_no_duplicates<float, float>{}, "");
Предположим, что для сферы применения этого вопроса я хочу сделать это с использованием множественного наследования.
Если класс наследуется от одного и того же типа более одного раза, возникает ошибка.
template<class T>
struct type { };
template<class... Ts>
struct dup_helper : type<Ts>... { };
// No errors, compiles properly.
dup_helper<int, float> ok{};
// Compile-time error:
// base class 'type<float>' specified more than once as a direct base class
dup_helper<float, float> error{};
Я предположил, что я мог бы использоваться для void_t
«обнаружить» эту ошибку, но я не мог реализовать рабочий раствор following the code samples from cppreference.
Это то, что я пробовал:
template<class, class = void>
struct is_valid
: std::false_type { };
// First try:
template<class T>
struct is_valid<T, std::void_t<decltype(T{})>>
: std::true_type { };
// Second try:
template<class T>
struct is_valid<T, std::void_t<T>>
: std::true_type { };
Для моей третьей попытки, я попытался задерживая расширение dup_helper<...>
с помощью класса-оболочки, который взял dup_helper
в качестве параметра шаблона шаблона, как wrapper<dup_helper, ...>
и расширенного его внутри void_t
,
К сожалению, все мои попытки привели к тому, что вышеупомянутая ошибка всегда предотвращала компиляцию.
Я предполагаю, что этот тип ошибки не обнаруживается как «сбой замены», но я бы хотел подтвердить.
Такую ошибку на самом деле невозможно обнаружить с помощью void_t
? (Будет ли это всегда приводить к сбою компиляции?)
Есть ли способ обнаружить его, не вызывая сбоя компиляции? (Или обходной способ, который по-прежнему использует «множественный улов наследования»)?
Я не думаю, что вы можете сделать эту работу с множественным наследованием. Проблема состоит в том, что это не декларация 'dup_helper', которая вызывает ошибку, но ее определение (если я не ошибаюсь). –
Caninonos
@ Caninonos В теории, Vittorio был инстанцированием 'T' в' decltype (T {}) ', затем получая тип. Витторио надеялся, что 'T {}' будет генерировать ошибку, потому что фактический оператор 'T {}' является ошибкой, даже если тип результата не является. – Yakk
@Yakk, но 'T {}' требует, чтобы компилятор определял 'T', и ошибка находится внутри его определения. Это похоже на попытку иметь ошибку в теле шаблонизированной функции (вместо ее возвращаемого типа возвращаемого типа/noexcept specifier/default template аргумент) и пытаться «поймать» его с помощью sfinae, я не думаю, что это возможно (Я не знаю точно, что говорит стандарт, но все же). (также, чтобы опубликовать «решение» с множественным наследованием, есть [это] (http://ideone.com/oT20iI), он абсолютно ненадежный, хотя, поскольку он полагается на EBO и размер пустого класса, t использовать его) – Caninonos