无法使用"enable_if"和"is_base_of"将模板函数"operator+"的重载限制到我的类层次结构
Can't restrict overload of template function `operator+` to my class hierarchy using `enable_if` and `is_base_of`
>我正在使用类型层次结构的模板函数创建一个operator+
。第一次简单的尝试工作正常,直到我尝试在代码的另一部分连接一个字符串,GCC 8.3 尝试使用我的operator+
。
尝试使用 enable_if
和 is_base_of
将我的版本限制为我的类型,以便 SFINAE 处理问题。
众多尝试中的一个是:
template < //
typename T1, //
typename T2, typename std::enable_if_t<std::is_base_of_v<LogicGateAbs, T2>, T2> //
>
inline OrGate operator +(T1&& lhs, T2&& rhs) {
return OrGate { LogicGateAbs::make_concrete(lhs), LogicGateAbs::make_concrete(rhs) };
}
在这里,编译器正确地给出了类型:
./src2/test.cpp:90:11: error: no match for ‘operator+’ (operand types are ‘TrueGate’ and ‘TrueGate’)
(True + True);
~~~~~^~~~~~
但是为什么它会为is_base_of
返回"false",因为LogicGateAbs
是TrueGate
的基础?
../src2/test.cpp:83:15: note: candidate: ‘template<class T1, class T2, typename std::enable_if<is_base_of_v<LogicGateAbs, T2>, T2>::type <anonymous> > OrGate operator+(T1&&, T2&&)’
inline OrGate operator +(T1&& lhs, T2&& rhs) {
^~~~~~~~
../src2/test.cpp:83:15: note: template argument deduction/substitution failed:
../src2/test.cpp:81:32: error: no type named ‘type’ in ‘struct std::enable_if<false, TrueGate&>’
typename T2, typename std::enable_if_t<std::is_base_of_v<LogicGateAbs, T2>, T2> //
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在StackOverflow上浏览了每个版本,但没有获得一个版本。
基本函数根据需要工作。右值引用是必需的,因为输入通常是临时值。
请注意错误消息中的TrueGate&
:这是T2
,因为参数是左值。 std:is_base_of
需要实际的类类型,因此请使用std::remove_reference_t
。
你需要::std::remove_reference
,是的。但是您还需要检查这两个参数的类型。:-/
template <typename T1, typename T2>
inline typename
::std::enable_if<
::std::is_base_of_v<LogicGateAbs, typename std::remove_reference_t<T1>> &&
::std::is_base_of_v<LogicGateAbs, typename std::remove_reference_t<T2>>,
AndGate>::type
operator *(T1 &&lhs, T2 &&rhs) {
using NRT1 = typename ::std::remove_reference<T1>::type;
using NRT2 = typename ::std::remove_reference<T2>::type;
AndGate gate { ::std::make_unique<NRT1>(::std::move(lhs)), ::std::make_unique<NRT2>(::std::move(rhs)) };
return gate;
}
现在,如果表达式的任何一侧不是从 LogicGateAbs
派生的,它将不匹配。我实际上对非模板版本有一种非常糟糕的感觉。这些仅在参数是临时参数时才有效。它适用于TrueGate
的唯一原因是它的移动构造函数等效于其复制构造函数。具有unique_ptr
成员的事物的移动构造函数是破坏性移动。
最终版本需要std::remove_reference_t
,=
由 @Davis 和 '@Sam 提供。向两者致敬。
在 LogicalGateAbs 中:
class LogicalGateAbs {
...
template <typename T>
static inline auto make_concrete(T&& rhs) {
using NRT = typename std::remove_reference<T>::type;
return std::make_unique < NRT > (std::move(rhs));
}
};
而operator+
的版本:
//----------------------------------------------------------------------
template <typename T>
using check_type = std::enable_if_t<std::is_base_of_v<LogicGateAbs, typename std::remove_reference_t<T>>, T>;
//-----------------------------------------------------------------------
template <typename T1, typename = check_type<T1>, typename T2, typename = check_type<T2> >
inline OrGate operator +(T1&& lhs, T2&& rhs) {
return OrGate { "op+", LogicGateAbs::make_concrete(lhs), LogicGateAbs::make_concrete(rhs) };
}
相关文章:
- 运算符重载:"operator+"必须采用零个或一个参数
- "operator()"在重载运算符方法中是什么意思,在priority_queue(STL)中用作C++中的比较器?
- 重载的 operator() 在 Cython 中失败
- C++ 继承:基类中重载 operator+ 的 2 次在派生类中无法正常工作
- 当试图交换可变模板类时,如何正确地重载operator=
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 从 std::ostream 重载 << 运算符时,为什么编译器会给出"too many parameters for this operator function"错误?
- 如何在不重载"operator()"、"std::less"、"std
- 如何在具有动态大小数组的模板化类中重载 operator=
- 重载 operator= 时返回引用和值有什么区别?
- 重载Operator =作为成员函数
- 在 STL 容器中存储具有重载"operator&"的类对象在 C++ 中合法吗?
- 重载operator<对于指向类对象的指针
- 重载operator< & lt;作为会员打印
- c++重载:operator =的重载
- 是否有一种方法可以重载operator=来为右边的函数提供特定的行为?
- 声明一个接受并返回` `流` `的函数有什么用?而不是重载operator<<
- 如何重载operator<<用于c++中的数组
- 重载运算符的模板:错误:重载'operator*'必须至少有一个类或枚举类型的参数
- 为什么在 std::string 上重载"operator <<"不起作用?