C++方法转发
C++ method forwarding
我需要实现一个类容器,它的作用与包含的模板类完全相同:
template <typename T>
class Container {
public:
//...
private:
// T data_;
};
T
可以是预定义类型(例如,int
)或用户定义的类型。
目的是截获对包含的类型执行的任何读/写操作。
我已经成功实现了大多数运算符,并且它有效。
但是,当我需要访问特定于所包含类 T 的方法时,它不起作用:
Container<myclass> a;
a.myclass_specific_method();
原因是容器显然没有这样的方法。此外,由于T是一个模板,因此无法事先知道其方法。
我想即使使用 C++11 也无法解决这个问题,因为operator .
不能超载。因此,唯一可能的方法是始终像智能指针一样依赖operator->
。
你能确认吗?
C++委员会目前正在研究"超载operator .
",以便将来对该语言进行修订。
但是,在特定情况下,只需从类型继承即可。
template <typename T>
class Container : private T {
public:
using T::something_publicly_accessible;
};
对于类类型T
,这将很像T
:
template<class T, class=void>
struct Container : public T { // inheritance MUST be public
using T::T;
Container() = default; // or override
Container( Container const& ) = default; // or override
Container( Container && ) = default; // or override
Container& operator=( Container const& ) = default; // or override
Container& operator=( Container && ) = default; // or override
// here, we override any method we want to intercept
// these are used by operators:
friend T& get_t(Container& self){return self;}
friend T const& get_t(Container const& self){return self;}
friend T&& get_t(Container&& self){return std::move(self);}
friend T const&& get_t(Container const&& self){return std::move(self);}
};
对于非类T
,我们检测它并使用不同的实现:
template<class T>
struct Container<T, typename std::enable_if<!std::is_class<T>{}>::type > {
T t;
Container() = default; // or override
Container( Container const& ) = default; // or override
Container( Container && ) = default; // or override
Container& operator=( Container const& ) = default; // or override
Container& operator=( Container && ) = default; // or override
// these are used by operators:
friend T& get_t(Container& self){return self.t;}
friend T const& get_t(Container const& self){return self.t;}
friend T&& get_t(Container&& self){return std::move(self).t;}
friend T const&& get_t(Container const&& self){return std::move(self).t;}
};
最后,我们以 SFINAE 友好的方式覆盖我们可以找到的每个运算符,其中操作员仅在get_t(Container)
可以在运算符中的位置工作时才参与过载解决。 这应该全部在命名空间中完成,因此可以通过 ADL 找到运算符。 返回其参数不变的 get_t
重载可能有助于大幅减少重载的数量。
这可能是另外 100 行或更多行代码。
Container<T>
用户可以绕过Container<T>
,获取上述系统中的底层T
。
您是否反对为内部data
成员设置一个getter?如果没有,那么您可以使用这样的东西
#include <iostream>
#include <string>
template <typename T>
class Container
{
public:
Container(T _data) : data{_data} {}
T GetData() const { return data; }
private:
T data;
};
int main()
{
Container<std::string> c{"foo"};
std::cout << c.GetData().size();
}
否则,您可以在内部访问该方法,并且仅当存在此方法时,该方法才会编译T
#include <iostream>
#include <string>
template <typename T>
class Container
{
public:
Container(T _data) : data{_data} {}
std::size_t size() const { return data.size(); }
private:
T data;
};
int main()
{
Container<std::string> c{"foo"};
std::cout << c.size();
}
因此,如果T
例如 std::string
、std::vector
、std::list
等
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 转发声明在命名空间中不起作用的替代方法
- C++或宏魔术来生成方法和转发参数
- C++11 重载方法,并转发到唯一方法
- 哪种设计更好:提供对所属对象的直接访问,或者为所属对象提供所属对象转发方法
- 通过列表和转发列表进行迭代的最有效方法
- 完美转发非模板类的方法
- 使用组合而不是继承的方法转发(使用C++特性)
- 是否有方法将所有赋值运算符(+=、*=等)转发为隐式使用重写的直接赋值运算符(=)
- 正确转发右值引用的方法
- 代理dll:方法覆盖/方法转发(COM实现继承)
- 转发不带签名的方法
- C++11虚拟模板方法或转发可变模板
- 转发类,无法访问方法
- C++方法转发
- 将调用转发到成员方法的模板