我試圖創建一個元組模擬以訪問其元素與相應的標記類型,而不是索引。我想出了一個解決方案(簡化):C++:帶標記類型訪問的元組
template<class T> struct tag { using type = T; };
using r = tag<double>;
using t = tag<double>;
using c = tag<int>;
template<class... Ts> class S
{
std::tuple<typename Ts::type&&...> data;
public:
S(typename Ts::type&&... args) : data(std::forward<typename Ts::type>(args)...) {}
};
int main()
{
r::type r0 = 0.;
const t::type t0 = 1.;
auto S0 = S<r, t, c>(r0, t0, 2); // <- error here
//auto T0 = std::forward_as_tuple(r0, t0, 2); // <- works!
}
然而,它沒有編譯器(gcc 7.2):
error: cannot bind rvalue reference of type ‘tag<double>::type&& {aka double&&}’ to lvalue of type ‘tag<double>::type {aka double}’
auto S0 = S<r, t, c>(r0, t0, 2);
^
note: initializing argument 1 of ‘S<Ts>::S(typename Ts::type&& ...) [with Ts = {tag<double>, tag<double>, tag<int>}]’
S(typename Ts::type&&... args) : data(std::forward<typename Ts::type>(args)...) {}
^
我發現std::forward_as_tuple
功能,能夠正確地推斷參數類型,所以我點是爲我的班級做同樣的事情。任何暗示我做錯了什麼?
UPD:初始描述不完整,抱歉。我的意圖不是存儲副本,而是引用(對於非const參數非const,對於const和rvalue引用const類似於std::forward_as_tuple
)。請參閱下面的更新代碼中的註釋:
template<class... Ts> class S
{
std::tuple<typename Ts::type...> data;
public:
template<class... Args>
S(Args&&... args) : data(std::forward<Args>(args)...) {}
template<size_t I> auto& get()
{
return std::get<I>(data);
}
};
int main()
{
r::type r0 = 0.;
const t::type t0 = 1.;
auto S0 = S<r, t, c>(r0, t0, 2);
S0.get<0>() = 111; // <- r0 is not changed!
S0.get<1>() = 222; // <- must not be possible!
auto T0 = std::forward_as_tuple(r0, t0, 2);
std::get<0>(T0) = 333; // <- r0 == 333
std::get<1>(T0) = 444; // <- compile error -- can't change const!
}
std :: tuple akready很好玩。 –
'typename Ts :: type &&'實際上是右值引用而不是轉發引用。 – Jarod42
@ n.m。不完全 - 我的目標是通過標記類型獲取值,而不是索引。標籤是可區分的,但實際類型不是 –