当试图交换可变模板类时,如何正确地重载operator=
How to properly overload operator= when trying to swap variadic templated classes?
我有一个类,其中我接受任意数量的类并将它们存储到std::tuple
中。它是一个可变模板类。我已经适当地使operator+
运算符过载,并且它们按预期工作。然而,现在我正试图将一个控制器类分配给另一个。我尝试过以下几种:
template<typename...ClassesR>
auto operator=(const Controller<ClassesR...>& rhs)
{
objects.swap(rhs.getObjects());
return *this;
}
然而,当我编译代码时,我得到了错误:"调用std::tuple<A&,B&>::swap(std::tuple<A&,B&,A&>)
没有匹配的函数
注意:参数1从std::tuple<A&,B&,A&>
到std::tuple<A&,B&>&
"没有已知的转换
简单地说,我正在尝试做以下事情:
ClassA A(3);
ClassB B(3.4);
ClassC C(4.5f);
Controller<ClassA,ClassB> controllerA(A,B);
Controller<ClassC> controllerB(C);
// thinking about it now, this might be the problem...because controllerA is actually
// Controller<ClassA,ClassB> and not Controller<ClassA,ClassB,ClassA>.
controllerA = controllerA + controllerB;
//or
//controllerA = controllerB;
这是我正在使用的代码:
#ifndef CONTROLLER_HPP
#define CONTROLLER_HPP
#include <functional>
#include <vector>
#include <utility>
#include <any>
template<typename...Classes>
class Controller
{
public:
Controller(Classes&...objects) : objects(objects...){ }
Controller(std::tuple<Classes&...> tup) : objects(tup){ }
//...a bunch of code that doesn't matter
std::tuple<Classes&...> getObjects() const
{
return objects;
}
template<typename...ClassesR>
auto operator=(const Controller<ClassesR...>& rhs)
{
objects.swap(rhs.getObjects());
return *this;
}
private:
std::tuple<Classes&...> objects;
};
template<typename...ClassesL, typename...ClassesR>
auto operator+(const Controller<ClassesL...>& lhs, const Controller<ClassesR...>& rhs)
{
return Controller(std::tuple_cat(lhs.getObjects(),rhs.getObjects()));
}
template<typename...ClassesL, typename ClassesR>
auto operator+(const Controller<ClassesL...> &lhs, ClassesR rhs)
{
Controller<ClassesR> makeController(rhs);
return Controller(std::tuple_cat(lhs.getObjects(),makeController.getObjects()));
}
template<typename ClassesL, typename...ClassesR>
auto operator+(ClassesL lhs, const Controller<ClassesR...> &rhs)
{
Controller<ClassesL> makeController(lhs);
return Controller(std::tuple_cat(makeController.getObjects(),rhs.getObjects()));
}
#endif // CONTROLLER_HPP
在这种情况下,使operator=
过载的正确方法是什么?正如我所指出的,在我写这篇文章的时候,这可能是因为模板化的类可能是一成不变的。所以Controller<ClassA,ClassB>
不能修改为Controller<ClassA,ClassB,ClassA>
,所以我可能需要返回一个新的控制器?
在C++中,对象永远不能更改其类型,并且类模板的各种专门化是不同的、不相关的类型。考虑一个假设的std::vector<int*>::operator=(const std::vector<bool>&)
;很明显,这是一个没有意义的请求,默认情况下,该限制会转移到任何类模板,即使它没有类型依赖于模板参数的成员。(其中一个次要原因是,通过继承、显式或部分专门化,允许专门化具有不相关的成员。(
因此,定义一个接受包含类模板的任何专门化的赋值运算符template通常是没有意义的:对它的数据根本无能为力(对于这种模板的大多数专门化(。即使类模板是无状态的,通过这样的定义来削弱类型系统通常也不是一个好主意。
当然,在语法和效率方面,有各种方法可以绕过这些限制。类型的(小(静态集合(尤其是类似大小的(可以保存在std::variant<…>
(内部是并集或字节缓冲区(中;一组无界的类型可以保存在std::any
中(除了小对象之外,它是内部指向堆分配的类型擦除指针(。
如本问题所示:运算符重载的基本规则和习惯用法是什么?,正确的方法是通过值接受对象,而不是通过const引用。例如:
auto& operator=(Controller<ClassesR...> rhs)
正如您所发现的,造成这种情况的部分原因(我假设(是,如果您经过const &
,您将被迫只使用const
函数。swap()
不是一个常数函数。
此外,auto
永远不是一个参考,除非你把它作为一个参考。因此,要遵循opertor=
习惯用法,需要返回一个auto&
。
更多关于这方面的信息比我所能解释的要好得多。
- 如何正确地将分支添加到已存在的树中
- 如何正确地将带有指针的数组传递给函数
- 如何正确地推回然后遍历堆中对象的向量?
- 我是否不正确地集中了这些字符数组?
- 如何通过另一个对象中的命令正确地从一个对象返回数据
- 我怎样才能通过友谊正确地履行我的职能?
- C++:如何正确地将 deque::front() 返回的变量从函数中传递出去?
- 如何正确使用重载的"运算符<<"?
- 我应该如何正确地将packaged_task移动到 lambda?
- 如何正确地将SHA1CryptoServiceProvider转换为c ++?
- 如何正确地对 constexpr 函数进行单元测试
- 我的动态链接队列在同一输出流中调用时不正确地输出三个返回函数
- 如何正确地将boost::asio::buffers_iterator转换为InputIterator
- 如何正确地检查变量char中包含的字母
- 当试图交换可变模板类时,如何正确地重载operator=
- 如何正确地将 boost::optional<std::chrono::d uration> 作为函数参数?
- 如何在C++中正确地将我的语言字符输出到HTML文件中
- 如果我的类正确地管理了一个资源,那么拥有智能的poointer有什么意义
- 在这种特定情况下,如何使用C++正确地重载运算符
- 在MATLAB mex文件中正确地重载字符串uf以替换cout