[英]C++ method forwarding
我需要實現一個類Container,其行為與包含的模板類完全相同:
template <typename T>
class Container {
public:
//...
private:
// T data_;
};
T
可以是預定義類型(例如, int
)或用戶定義類型。
目的是攔截對包含類型執行的任何讀/寫操作。
我已成功實現了大多數運算符,並且它可以工作。
但是,當我需要訪問特定於包含的類T的方法時,它不起作用:
Container<myclass> a;
a.myclass_specific_method();
原因是Container顯然沒有這樣的方法。 此外,由於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)
在運算符中的位置運行,則運算符僅參與重載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
等,后一種方法就可以工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.