그래서 주어진 다음 2 개 기능 :lvalues 및 rvalues의 목록을 참조 유형 및 전체 유형이있는 튜플로 변환하는 방법이 있습니까?
int rvalue();
int& lvalue();
유효한 것 다음
std::tuple<int&, int> x = appropriate_fn(lvalue(), rvalue());
내가 이런 식으로 같은 것을 생각했다 :
template <typename T, typename...Ts>
auto make_comparible(T const& arg, Ts&&...args)
{
return std::make_tuple(T(arg), make_comparible(args...));
}
template <typename T, typename...Ts>
auto make_comparible(T& arg, Ts&&...args)
{
return std::make_tuple<T&>(arg, make_comparible(args...));
}
template <typename T>
auto make_comparible(T const& arg)
{
return std::tuple<T>(T(arg));
}
template <typename T>
auto make_comparible(T& arg)
{
return std::tuple<T&>(arg);
}
을하지만 거기에 세 가지 문제이 내가 볼 수있는.
이것은 단순한
std::tuple
이 아니라 중첩 된 것입니다. 생각 해봐야 할 것은 문제가되지 않을 수도 있습니다. 단지 비교를하고 싶습니다 (보다 작거나 같음). 여전히 작동해야합니다.이것은 임시 참조와 const 참조를 구분하지 않습니다. 이것은 약간 짜증나지만 주위에 어떤 방법도 보이지 않습니다.
가장 중요한 것은 작동하지 않습니다. 다음 감안할 때 :
std::tuple<int, std::tuple<int&>> x = make_comparible(rvalue(), lvalue()); std::tuple<int&, std::tuple<int>> y = make_comparible(lvalue(), rvalue());
첫 번째 작품이지만,
make_comparible()
는std::tuple<int&, std::tuple<int>>
대신std::tuple<int, std::tuple<int&>>
를 반환하기 때문에 두 번째 오류를 제공합니다. 그래서 Demo
, 나는 수에 대한 부탁 해요, 또는 파이프의 꿈은 무엇입니까?
사용 사례는 튜플 (또는 비슷한 유형)을 반환하는 클래스에서 함수를 정의하고 싶지만 포인터/참조가 매 핑되지 않으며 사용하기 쉽습니다.
는
이 좋아, 그래서 C++ and Beyond 2012: Scott Meyers - Universal References in C++11을보고 한 후, 그것은 보편적 인 기준에 과부하처럼 보이는 편집은 거의 항상 오류가 발생합니다. 그러나 lvalue를 rvalue와 차별화하려고 시도 할 때 constity와 관계없이 이것이 올바른 방법 일 것입니다.
lvalues에 대한 과부하를 선언하면 overloading을 사용하여 범용 참조가 rvalues에만 바인딩되도록 할 수 있습니다. 나는 또한 내 편의 두뇌 방구였던 std::forward()
을 사용하는 것을 잊었다. 나는 더 잘 알고 있어야했다.
#include <iostream>
#include <tuple>
// forward declarations
template <typename T, typename...Ts>
decltype(auto) make_comparible(T const& arg, Ts&&...args);
template <typename T, typename...Ts>
decltype(auto) make_comparible(T& arg, Ts&&...args);
template <typename T>
decltype(auto) make_comparible(T&& arg);
template <typename T>
decltype(auto) make_comparible(T const& arg);
template <typename T>
decltype(auto) make_comparible(T& arg);
// rvalue
template <typename T, typename...Ts>
decltype(auto) make_comparible(T&& arg, Ts&&...args)
{
std::cout << "rvalue ";
// want to copy, so do not use std::move()
return std::make_tuple(arg, make_comparible(std::forward<Ts>(args)...));
}
// lvalue const
template <typename T, typename...Ts>
decltype(auto) make_comparible(T const& arg, Ts&&...args)
{
std::cout << "lvalue const ref ";
// This is a reference, so store as a reference
return std::make_tuple<T const&>(arg, make_comparible(std::forward<Ts>(args)...));
}
// lvalue
template <typename T, typename...Ts>
decltype(auto) make_comparible(T& arg, Ts&&...args)
{
std::cout << "lvalue ref ";
// This is a reference, so store as a reference
return std::make_tuple<T&>(arg, make_comparible(std::forward<Ts>(args)...));
}
// rvalue
template <typename T>
decltype(auto) make_comparible(T&& arg)
{
std::cout << "rvalue ";
// want to copy, so do not use std::move()
return std::tuple<T>(arg);
}
// lvalue const
template <typename T>
decltype(auto) make_comparible(T const& arg)
{
std::cout << "lvalue const ref ";
// This is a reference, so store as a reference
return std::tuple<T const&>(arg);
}
// lvalue
template <typename T>
decltype(auto) make_comparible(T& arg)
{
std::cout << "lvalue ref ";
// This is a reference, so store as a reference
return std::tuple<T&>(arg);
}
int var = 5;
int rvalue() { return 4; }
int& lvalue() { return var; }
int const& const_lvalue() { return var; }
int main()
{
// expect output "rvalue lvalue ref", OK
std::tuple<int, std::tuple<int&>> x = make_comparible(rvalue(), lvalue());
std::cout << std::endl;
// expect output "rvalue lvalue const ref", OK
std::tuple<int, std::tuple<int const&>> y = make_comparible(rvalue(), const_lvalue());
std::cout << std::endl;
// expect output "lvalue ref lvalue const ref rvalue", OK
make_comparible(lvalue(), const_lvalue(), rvalue());
// But this doesn't work. Type returned was std::tuple<int, std::tuple<int, std::tuple<int> > >. WHY?
std::tuple<int&, std::tuple<int const&, std::tuple<int>>> z = make_comparible(lvalue(), const_lvalue(), rvalue());
std::cout << std::endl;
return 0;
}
코드 경로가 정확합니다. 그러나 반환 된 유형이 잘못되었습니다. std::tuple<int&, std::tuple<int const&, std::tuple<int>>>
대신 std::tuple<int, std::tuple<int, std::tuple<int>>>
이 표시됩니다. 왜? 난 당신이 원하는 게 무엇인지 제대로 이해하고
'decltype (자동)' – Zereges
@ max66. 고정 – Adrian