일종의. T
에 대한 정방향 참조 개념을 입력하여 지울 수 있습니다.
template<class T>
struct forward_ref {
using extract_sig = T(void*);
using get_sig = T const&(void*);
extract_sig* extract = nullptr;
get_sig* gettor = nullptr;
void* pvoid;
template<class U>
void wrap(U&& t) {
auto* pt = std::addressof(t);
using pT = decltype(pt);
pvoid = const_cast<void*>(static_cast<void const*>(pt));
gettor = [](void* pvoid)->T const& {
// std::cout << "getting:\n";
auto* pt = static_cast<pT>(pvoid);
return *pt;
};
extract = [](void* pvoid)->T {
// std::cout << "extracting via " << (std::is_rvalue_reference<U&&>::value?"move":"copy") << "\n";
auto* pt = static_cast<pT>(pvoid);
return std::forward<U>(*pt);
};
}
forward_ref(T const& t){ wrap(t); }
forward_ref(T && t = {}){ wrap(std::move(t)); }
bool valid() const { return gettor&&extract; }
operator T()&&{
// std::cout << "operator T&&\n";
T r = extract(pvoid);
// std::cout << "extracted\n";
gettor=nullptr; extract=nullptr; pvoid=nullptr;
return r;
}
operator T const&() const &{
// std::cout << "operator T const&\n";
return gettor(pvoid);
}
T get()&& { return std::move(*this); }
T const& get() const& { return *this; }
};
그래서 당신은이 작업을 수행 할 수 있습니다
void Foo(forward_ref<std::string> s); // rvalue-reference
과 std::string
에 전달 유사한 참조 s
동작합니다을 (어느 정도).
std::move
이 s
인 경우 수신 된 std::string
을 복사하거나 그 값이 rvalue 또는 lvalue인지에 따라 이동합니다.
지금이
void Foo(std::string s)
이 될 것입니다 때문에 거의 위의 그 화려한
forward_ref
보다 더 나은 생각을가는 요리, 꽤 바보입니다.
이동이 저렴하고 복사본을 stprimg 할 계획이라면 값을 가져 오는 것이 전달 참조와 거의 비슷합니다.
이동이 복사보다 저렴하면 const&
으로 가져 가십시오.
이동이 비싸고 복사가 훨씬 비쌉니다.
전달 참조는 일반적인 코드에서 이동이 저렴하다는 것을 모르기 때문에 유용합니다. 당신이 아는 구체적인 유형.
어쨌든 live example은 정방향 참조를 삭제했습니다.
'const &'는'&&'가 존재하기 전에 어떻게 행해졌습니까. – NathanOliver
SFINAE를 사용하여 항상 유형을 제한 할 수 있습니다. – Rakete1111
'lvalue-reference (&)를 사용할 때 비 const 객체에 바인딩 할 수 없습니다. 물론 lvalue-reference를 const가 아닌 객체에 바인딩 할 수 있습니다. 아마도 당신은 const가 아닌 참조가 const 객체에 바인딩 할 수 없다는 것을 의미했을까요? 또는 비 const 레퍼런스는 (임시처럼) rvalue에 바인딩 할 수 없습니까? – user2079303