【发布时间】:2020-06-17 10:51:34
【问题描述】:
以下代码在 MSVC 2019 和 Clang 主干上编译和运行。 (我认为它至少需要 C++17)。它不能在 gcc-trunk 上运行,我认为这是由于 gcc 中的错误造成的。
但是,当任何元素被用户类型或指针类型替换时,它在所有编译器上都会失败。要查看此内容,请取消注释末尾附近的 tuple_c 定义。
我实际上有点惊讶它的工作原理,因为它似乎是用一个具有通用引用参数的函数和一个具有 r-value-ref 参数的函数。也许没关系?如果是,为什么结构会失败?
有没有更好的写法?我的意思是一般。我很清楚std::tuple。
#include <iostream>
using namespace std;
template <typename... TP> class Tuple
{
};
template <> class Tuple <>
{
};
template <typename Head, typename... Tail> class Tuple <Head, Tail...>
{
Head head;
Tuple <Tail...> tail;
public:
Tuple ()
{
}
Tuple (const Head& head_in, const Tail&...tail_in)
: head (head_in), tail (tail_in...)
{
}
template <int i> auto Get ()
{
return tail.template Get <i-1> ();
}
template <> auto Get <0> ()
{
return head;
}
template <int i, typename T> void Set (T&& v) // T&& is a universal ref
{
tail.template Set <i-1, T> (static_cast <T&&> (v));
}
template <int i, typename T> void Set (const T& v)
{
tail.template Set <i-1, T> (v);
}
template <> void Set <0, Head> (Head&& v) // Head&& is an rv-ref
{
head = v;
}
template <> void Set <0, Head> (const Head& v)
{
head = v;
}
};
template <typename Head, typename... Tail> Tuple <Head, Tail...> MakeTuple (Head&& head, Tail&&...tail)
{
Tuple <Head, Tail...> result (head, tail...);
return result;
}
struct S
{
int x;
int y;
};
ostream& operator << (ostream& out, const S& s)
{
out << "{" << s.x << "," << s.y << "}";
return out;
}
int main(int argc, char* argv[])
{
auto tuple_a = MakeTuple (1,2,3,4);
tuple_a.Set <1,int> (42);
cout << tuple_a.Get <0> () << '\n';
cout << tuple_a.Get <1> () << '\n';
cout << tuple_a.Get <2> () << '\n';
cout << tuple_a.Get <3> () << '\n';
auto tuple_b = MakeTuple (1,2.3f,3,4);
tuple_b.Set <1,float> (42.3f);
cout << tuple_b.Get <0> () << '\n';
cout << tuple_b.Get <1> () << '\n';
cout << tuple_b.Get <2> () << '\n';
cout << tuple_b.Get <3> () << '\n';
S s {4,5};
//auto tuple_c = MakeTuple (1,2.3f,3,s);
return 0;
}
【问题讨论】:
-
请创建一个minimal reproducible example。您的大部分代码与您的问题无关,只是增加了我们必须扫除的噪音。
-
还添加了确切的编译器错误消息,并指出它发生在哪一行。
-
gcc 10 在到达
main()部分之前就放弃了。如果没有明确的错误消息和minimal reproducible example,则无法重现所提出的问题。 -
我确实尝试通过手动扩展实例化来缩小范围。在我看来,它看起来并不简单。我假设每个人都可以复制粘贴到编译器资源管理器中。我从编译器资源管理器中复制粘贴了它,所以它应该可以工作。 MSVC 说:source>(46): error C2535: 'void Tuple
::Set(Head)': member function already defined or declared – Rob190 just now
标签: c++ templates variadic-templates template-argument-deduction