我正在尝试为练习制作自己的tuple
实施方案。我试图将std::string
作为rvalue
传递给我的元组。但是,我无法获取编译代码,我想知道如何解决这个问题。我理解它会衰减到char * const
,并将其替换为我的模板参数,但是当使用std::make_tuple(Args&&...)
的标准库版本尝试类似的代码时,rvalue reference
没有问题。所以我很好奇我在实现中缺少的内容以及如何解决它。为了深入理解,将理解详细说明。
的main.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;
}
tuple.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)...);
}
答案 0 :(得分:1)
makeTuple(1, b, 'c', "test")
返回Tuple<int, int, char, const char*>
。然后,您尝试从该元组复制构造Tuple<int, int, char, std::string>
,这不起作用,因为Tuple<int, int, char, std::string>
的构造函数需要int
类型的参数,{{1 },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))
{}
参数的存在是为了避免在您实际尝试创建包含单个std::enable_if_t
的{{1}}时选择转换构造函数。