簡體   English   中英

C ++方法轉發

[英]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::stringstd::vectorstd::list等,后一種方法就可以工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM