c++ - std::make_tuple 是右值引用时如何保留 std::string 类型

标签 c++ c++11 templates template-meta-programming

我正在尝试制作自己的 tuple 实现以供练习。我试图将 std::string 作为 rvalue 传递到我的元组中。但是,我无法编译代码,想知道如何解决这个问题。我知道它会衰减为 char * const,并将其代入我的模板参数中是可行的,但是当尝试使用标准库版本的 std::make_tuple(Args&&... ) 右值引用 没有问题。所以我很好奇我在实现中遗漏了什么以及如何修复它。深入理解的详细解释将不胜感激。

主要.cpp

int main()
{
  //Tuple<int, int> int_tuple = custom_make_tuple(1, 2);
  int a = 1;
  int b = 1;
  std::string Testing = "testing";

  Tuple<int, int, char, std::string> t1 = makeTuple(1, b, 'c', "test"); //Fails to compile
  Tuple<int, int, char, std::string> t1 = makeTuple(1, b, 'c', Testing); //OK
  std::tuple<std::string> test = std::make_tuple("test"); //OK

  return 0;
}

元组.h

template<typename... Types>
class Tuple;

// recursive case:
template<typename Head, typename... Tail>
class Tuple<Head, Tail...>
{
private:
  Head head;
  Tuple<Tail...> tail;
public:
  constexpr Tuple() {
  }

  template<typename FHead, typename... FTail>
  constexpr Tuple(FHead && head, FTail &&... tail)
    : head(std::forward<FHead>(head)), tail(std::forward<FTail>(tail)...) {}

  constexpr Head& GetHead() { return head; }
  constexpr Head const& GetHead() const { return head; }
  constexpr Tuple<Tail...>& GetTail() { return tail; }
  constexpr Tuple<Tail...> const& GetTail() const { return tail; }
};

// basis case:
template<>
class Tuple<> {};

template<typename... Eles>
constexpr auto makeTuple(Eles&&... elems)
{
  return Tuple<std::decay_t<Eles>...>(std::forward<Eles>(elems)...);
}

最佳答案

makeTuple(1, b, 'c', "test")返回 Tuple<int, int, char, const char*> .然后你尝试复制构建一个 Tuple<int, int, char, std::string>从那个元组,这是行不通的,因为 Tuple<int, int, char, std::string>的构造函数需要类型为 int 的参数, int , char , 和 std::string , 不是 Tuple<int, int, char, const char*> .

您需要添加转换构造函数来接受元组并将包含的对象转换为您需要的类型:

template <typename... Types>
friend class Tuple;

template<typename FHead, typename... FTail,
         std::enable_if_t<sizeof...(Tail) + 1 == sizeof...(FTail) + 1>* = nullptr>
constexpr Tuple(const Tuple<FHead, FTail...>& o)
  : head(o.head), tail(o.tail)
{}

template<typename FHead, typename... FTail,
         std::enable_if_t<sizeof...(Tail) + 1 == sizeof...(FTail) + 1>* = nullptr>
constexpr Tuple(Tuple<FHead, FTail...>&& o)
  : head(std::move(o.head)), tail(std::move(o.tail))
{}

Live Demo

请注意 std::enable_if_t存在参数是为了避免在您实际尝试创建 Tuple 时选择转换构造函数包含单个 Tuple .

关于c++ - std::make_tuple 是右值引用时如何保留 std::string 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49419611/

相关文章:

c++ - 在cuda中使用静态成员函数模板结构的替代方法?

c++ - winapi - 从 QObject 派生类调用时 GetMessage() 崩溃

C++ DirectX CreateDevice 从全窗口游戏

c++ - FFmpeg 解码和转换 RGB sws_scale 错误

c++ - 为什么C++标准要为std::bitset::reference指定一个析构函数?

c++ - 我可以列表初始化一个只 move 类型的 vector 吗?

c++ - 我想创建一个 std::function 但逐渐添加 args

c++ - 如何使用 CMake 链接多个库

c++ - 类模板静态数据成员定义/声明/初始化

c++ - 模板类中的 Typedef 不起作用