включить, если тип не относится к определенному классу шаблона
Дву: смотрите последний абзац.
У меня есть operator&
, определенный для нескольких классов шаблонов, таких как:
template <typename T>
struct Class {
Class(T const &t) { }
};
template <typename T_Lhs, typename T_Rhs>
struct ClassAnd {
ClassAnd(T_Lhs const &lhs, T_Rhs const &rhs) { }
};
template <typename T, typename T_Rhs>
ClassAnd<Class<T>, T_Rhs> operator&(Class<T> const &lhs, T_Rhs const &rhs) {
return ClassAnd<Class<T>, T_Rhs>(lhs, rhs);
}
template <typename T0, typename T1, typename T_Rhs>
ClassAnd<ClassAnd<T0, T1>, T_Rhs> operator&(ClassAnd<T0, T1> const &lhs, T_Rhs const &rhs) {
return ClassAnd<ClassAnd<T0, T1>, T_Rhs>(lhs, rhs);
}
int main() {
Class<int> a(42);
Class<double> b(3.14);
auto c = a & b;
}
Это работает просто отлично.
Проблема возникает, когда я хочу добавить операцию не, которая разрешена только с одной или другой стороны операции и и должна возвращать экземпляр ClassAndNot
, а не ClassAnd
:
template <typename T>
struct ClassNot {
ClassNot(T const &t) : value(t) { }
T value;
};
template <typename T_Lhs, typename T_Rhs>
struct ClassAndNot {
ClassAndNot(T_Lhs const &lhs, T_Rhs const &rhs) { }
};
template <typename T_Lhs, typename T_Rhs>
ClassAndNot<T_Lhs, T_Rhs> operator&(T_Lhs const &lhs, ClassNot<T_Rhs> const &rhs) {
return ClassAndNot<T_Lhs, T_Rhs>(lhs, rhs.value);
}
template <typename T_Rhs>
ClassNot<T> operator!(T_Rhs const &rhs) {
return ClassNot<T_Rhs>(rhs);
}
...
auto c = a & !b;
Это приводит к неоднозначности между operator&
, принимающим произвольную правую сторону для возврата a ClassAnd
, и operator&
, принимающим a ClassNot
правая сторона, чтобы вернуть a ClassAndNot
.
Вопрос:
Как здесь можно использовать std::enable_if
для отключения Первого operator&
, если его правая сторона относится к любому из типов ClassNot
? Существует ли что-то вроде std::is_same
, которое возвращает true, если одна сторона является шаблонным экземпляром другой?
P. s. Вы можете найти полный рабочий пример наideon .
1 ответ:
Вы должны быть в состоянии построить свой собственный признак для этого:
template <class T> struct IsClassNot : std::false_type {}; template <class T> struct IsClassNot<ClassNot<T>> : std::true_type {}; template <typename T, typename T_Rhs> typename std::enable_if<!IsClassNot<T_Rhs>::value, ClassAnd<Class<T>, T_Rhs>>::type operator&(Class<T> const &lhs, T_Rhs const &rhs) { return ClassAnd<Class<T>, T_Rhs>(lhs, rhs); }
Живой пример
Конечно, вы можете сойти с ума от обобщений и создать универсальную черту:template <class T, template <class...> class TT> struct is_instantiation_of : std::false_type {}; template <template <class... > class TT, class... A> struct is_instantiation_of<TT<A...>, TT> : std::true_type {}; template <class T> using IsClassNot = is_instantiation_of<T, ClassNot>;
Живой пример