Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;方法转发_C++_Templates_C++11_Operator Overloading_Perfect Forwarding - Fatal编程技术网

C++ C++;方法转发

C++ C++;方法转发,c++,templates,c++11,operator-overloading,perfect-forwarding,C++,Templates,C++11,Operator Overloading,Perfect Forwarding,我需要实现一个类容器,其作用与所包含的模板类完全相同: template <typename T> class Container { public: //... private: // T data_; }; 原因是容器显然没有这样的方法。此外,由于T是一个模板,其方法无法预先知道 我想即使使用C++11,也无法解决这个问题,因为运算符。不能重载。因此,唯一可能的方法是像智能指针一样始终依赖运算符-> 您能确认吗?您是否反对为内部数据成员使用getter?

我需要实现一个类容器,其作用与所包含的模板类完全相同:

template <typename T>
class Container {
public:
      //...
private:
      // T data_;
};
原因是容器显然没有这样的方法。此外,由于T是一个模板,其方法无法预先知道

我想即使使用C++11,也无法解决这个问题,因为
运算符。
不能重载。因此,唯一可能的方法是像智能指针一样始终依赖
运算符->


您能确认吗?

您是否反对为内部
数据
成员使用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();
}

<> P> >如果代码< > t>代码>例如:代码> STD::String ,代码> STD::向量, STD::列表

< P> C++委员会目前正在寻找“过载<代码>操作符> <代码> >,用于语言的未来修订。

但是,在您的特定情况下,您可以简单地从类型继承

template <typename T>
class Container : private T {
public:
    using T::something_publicly_accessible;
};
模板
类容器:private T{
公众:
使用T::可以公开访问的东西;
};

对于类类型
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);}
};
最后,我们以一种SFINAE友好的方式去覆盖我们能找到的每个操作符,如果
get\t(Container)
在操作符中的位置工作,那么操作符只参与重载解析。这一切都应该在一个名称空间中完成,因此可以通过ADL找到运算符。
get\t
的重载返回其参数不变,这有助于大量减少重载的数量

这可能是另外100行或更多的代码


Container
的用户可以绕过
Container
在上述系统中获取底层的
T

您不能为
数据提供一个访问器(getter)并像这样使用它:
a.get().myclass\u-specific\u-method()?不,我不能。我希望容器对程序员尽可能透明。如果方法只来自已知的集合,那么SFINAE可以很好地知道委员会(最终)考虑到
操作符的重载。
我忘了说的一点是类的目的:截取对所包含类型的任何读/写操作。不幸的是,我无法从类型继承,因为当我实现
operator=(T other)
对语句
T::operator=(other)的调用时对于预定义类型(例如,
int
)失败。是,重载
运算符会很好。。。共享参考!你能指出一些状态吗?@AmiTavory这不是CRTP。CRTP是颠倒的。@Claudio也许您应该将内置类型包装在代理类中,然后从代理继承。为内置类型定义代理的最简单方法是提供
templatestruct proxy{T obj;操作符T&({return obj;})操作符T const&({return obj;})。转换将使内置运算符能够工作,因此您不需要自己重载它们。不幸的是,
t
甚至可以是用户定义的类。此外,我不能使用getter,因为API必须对程序员尽可能透明(尽可能少入侵)。谢谢。但是,除了
std::enable_if_t
可能应该是
std::enable_if
,一个简单的
容器
没有编译,因为它抱怨
错误:基类型“int”不能是结构或类类型
。你能检查一下吗?@claudio
typename std::enable_if::type
替换了C++11编译器中的
std::enable_if_t
。缺少类型/类型名会使它无法执行它应该执行的操作(将非类,如
int
,重定向到第二个实现)再次感谢您。那么,你为什么不修改代码,让它可以在任何C++11编译器上运行呢?@claudio,因为它在C++14中看起来不那么难看,而我现在正在电话上与你聊天,因此很懒。请随时在中编辑更正!我觉得用C++11编写它比用C++14编写要好,所以它也适用于较旧的编译器。我改了。再次感谢。
template <typename T>
class Container : private T {
public:
    using T::something_publicly_accessible;
};
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);}
};
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;}
};