我想在我的类“Record”中隐藏一个 std::tuple 并在其上提供一个 operator[] 来访问元组的元素。不编译的天真代码是这样的:
#include <tuple>
template <typename... Fields>
class Record {
private:
std::tuple<Fields...> list;
public:
Record() {}
auto operator[](std::size_t n)
-> decltype(std::get<1u>(list)) {
return std::get<n>(list);
}
};
int main() {
Record<int, double> r;
r[0];
return 0;
}
g++ 4.6 说:
x.cc:13:32: error: no matching function for call to ‘get(std::tuple<int, double>&)’
x.cc:13:32: note: candidates are:
/usr/include/c++/4.6/utility:133:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/utility:138:5: note: template<unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&)
/usr/include/c++/4.6/tuple:531:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&)
/usr/include/c++/4.6/tuple:538:5: note: template<unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&)
基本上我想调用 Record::operator[]
就像在数组上一样。这可能吗?
最佳答案
get
的参数是一个编译时常量。你不能使用
为此的运行时变量,你不能有一个单一的功能
返回 tuple
成员,因为您的返回类型将是
错误的。你可以做的是滥用非类型参数推导:
#include <tuple>
template<typename... Args>
struct Foo {
std::tuple<Args...> t;
template<typename T, std::size_t i>
auto operator[](T (&)[i]) -> decltype(std::get<i>(t)) {
return std::get<i>(t);
}
// also a const version
};
int main()
{
Foo<int, double> f;
int b[1];
f[b];
return 0;
}
这太可怕了,我永远不会使用它,它对用户来说也没有多大意义。我只是通过模板成员转发 get
。
我将尝试解释为什么我认为这真的很邪恶:函数的返回类型仅取决于编译时事实(这对于 virtual
成员函数略有变化)。让我们假设在某些情况下可以进行非类型参数推导(函数调用参数是 constexpr
),或者我们可以构建一些可以很好地隐藏它的东西,您的用户不会意识到他们的返回类型刚刚改变,隐式转换会对它们造成讨厌的事情。明确这一点可以避免一些麻烦。
关于C++ 将非模板成员函数调用转发到模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9150198/