先上代码,注意 get 函数和其友元函数
#include <utility>
#include <type_traits>
template <unsigned Height, typename T, bool = std::is_class_v<T> && !std::is_final_v<T>>
class TupleElt;
template <unsigned Height, typename T>
class TupleElt<Height, T, false>
{
private:
T value;
public:
TupleElt() = default;
template <typename U>
TupleElt(U &&other) : value(std::forward<U>(other)) {}
T &get() { return value; }
T const &get() const { return value; }
};
template <unsigned Height, typename T>
class TupleElt<Height, T, true> : private T
{
public:
TupleElt() = default;
template <typename U>
TupleElt(U &&other) : T(std::forward<U>(other)) {}
T &get() { return *this; }
T const &get() const { return *this; }
};
template <unsigned H, typename T>
T &getHeight(TupleElt<H, T> &te)
{
return te.get();
}
template <typename... Types>
class Tuple;
template <unsigned I, typename... Elements>
auto get(Tuple<Elements...> &t) -> decltype(getHeight<sizeof...(Elements) - I - 1>(t))
{
return getHeight<sizeof...(Elements) - I - 1>(t);
}
template <typename... Types>
class Tuple;
template <typename Head, typename... Tail>
class Tuple<Head, Tail...> : private TupleElt<sizeof...(Tail), Head>, private Tuple<Tail...>
{
template <unsigned I, typename... Elements>
friend auto get(Tuple<Elements...> &t) -> decltype(getHeight<sizeof...(Elements) - I - 1>(t)); \\ 友元函数声明
private:
using HeadElt = TupleElt<sizeof...(Tail), Head>;
public:
Head &getHead() { return static_cast<HeadElt *>(this)->get(); }
Head const &getHead() const { return static_cast<HeadElt const *>(this)->get(); }
Tuple<Tail...> &getTail() { return *this; }
Tuple<Tail...> const &getTail() const { return *this; }
};
template <>
class Tuple<>
{
};
int main()
{
Tuple<char, char> t1;
get<0>(t1);
return 0
}
我跟着 C++ templates 2nd edition, 实现了一个简单的 tuple 类和 get 函数,其中 tuple 类里面的元素被 tuple 类私有继承,get 函数通过计算元素高度,来实现直接从派生类到基类的转换来访问对应的元素,由于 tupleElt 类被私有继承,get 函数必须在 tuple 类中被声明为友元函数才可以被访问(上述代码注释处)但是即使被声明为了友元函数,gcc 还是提示 get 函数无法访问 tuple 的基类,导致编译错误,但 MSVC 可以顺利编译通过,是为什么呢,如果有错误该怎么改?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.