I need to implement a class Container which acts exactly as the contained template class:
template <typename T>
class Container {
public:
//...
private:
// T data_;
};
T
can be either a predefined type (eg, int
) or a user-defined type.
The purpose is to intercept any read/write operations done on the contained type.
I've succesfully implemented most operators, and it works.
However, when I need to access methods specific of the contained class T, it doesn't work:
Container<myclass> a;
a.myclass_specific_method();
The reason is that Container obviously doesn't have such methods. Moreover, since T is a template, its methods cannot be known in advance.
I guess there is no solution to this problem, even with C++11, because operator .
cannot be overloaded. Therefore, the only possible approach is to always rely on operator->
like smart pointers do.
Can you confirm ?
The C++ committee is currently looking into "overloaded operator .
" for future revisions of the language.
However, in your specific case, you can simply inherit from the type.
template <typename T>
class Container : private T {
public:
using T::something_publicly_accessible;
};
For a class type T
, this will act a lot like a 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);}
};
for a non-class T
, we detect it and use a different implementation:
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;}
};
finally, we go off and override every operator we can find in a SFINAE friendly way, where the operator only participates in overload resolution if get_t(Container)
would work in its place in the operator. This should all be done in a namespace, so the operators are found via ADL. An overload of get_t
that returns its argument unchanged could be useful to massively reduce the number of overloads.
This could be another 100 or more lines of code.
Users of Container<T>
can bypass the Container<T>
and get the underlying T
in the above system.
Are you opposed to having a getter for the inner data
member? If no, then you can use something like this
#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();
}
Otherwise you could internally access the method, and it will only compile if such a method exists for 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();
}
So this latter method would work if T
was eg std::string
, std::vector
, std::list
, etc.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.