C++方法转发
C++ method forwarding
我需要实现一个 class 容器,它与包含的模板完全一样 class:
template <typename T>
class Container {
public:
//...
private:
// T data_;
};
T
可以是预定义类型(例如 int
)或用户定义类型。
目的是拦截对包含的类型执行的任何 read/write 操作。
我已经成功地实现了大多数运算符,而且很有效。
但是,当我需要访问包含的 class T 的特定方法时,它不起作用:
Container<myclass> a;
a.myclass_specific_method();
原因是Container显然没有这样的方法。而且,由于T是一个模板,它的方法不能提前知道。
我想这个问题没有解决方案,即使使用 C++11,因为 operator .
不能重载。因此,唯一可能的方法就是像智能指针一样始终依赖 operator->
。
你能确认一下吗?
您是否反对为内部 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
等
C++ 委员会目前正在研究 "overloaded operator .
" 语言的未来修订。
但是,在您的特定情况下,您可以简单地从类型继承。
template <typename T>
class Container : private T {
public:
using T::something_publicly_accessible;
};
对于 class 类型 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);}
};
对于非class 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
的重载 returns 其参数不变可能有助于大量减少重载的数量。
这可能是另外 100 行或更多代码。
Container<T>
的用户可以绕过Container<T>
,获取上述系统中的底层T
。
我需要实现一个 class 容器,它与包含的模板完全一样 class:
template <typename T>
class Container {
public:
//...
private:
// T data_;
};
T
可以是预定义类型(例如 int
)或用户定义类型。
目的是拦截对包含的类型执行的任何 read/write 操作。
我已经成功地实现了大多数运算符,而且很有效。
但是,当我需要访问包含的 class T 的特定方法时,它不起作用:
Container<myclass> a;
a.myclass_specific_method();
原因是Container显然没有这样的方法。而且,由于T是一个模板,它的方法不能提前知道。
我想这个问题没有解决方案,即使使用 C++11,因为 operator .
不能重载。因此,唯一可能的方法就是像智能指针一样始终依赖 operator->
。
你能确认一下吗?
您是否反对为内部 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
等
C++ 委员会目前正在研究 "overloaded operator .
" 语言的未来修订。
但是,在您的特定情况下,您可以简单地从类型继承。
template <typename T>
class Container : private T {
public:
using T::something_publicly_accessible;
};
对于 class 类型 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);}
};
对于非class 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
的重载 returns 其参数不变可能有助于大量减少重载的数量。
这可能是另外 100 行或更多代码。
Container<T>
的用户可以绕过Container<T>
,获取上述系统中的底层T
。