2014-11-21 2 views
14

Recently I've discovered 가끔 우변으로 번으로 바꿀 수있는 것은 일 수 있습니다.함수에 전달하기 위해 xvalues를 lvalues로 형 변환하는 것이 잘 정의되어 있습니까?

나는 다음과 같은 도구를 사용하고있다 :

#include <type_traits> 

template <typename T> 
inline constexpr std::remove_reference_t<T> &lvalue(T &&r) noexcept { 
    return static_cast<std::remove_reference_t<T> &>(r); 
} 

당신이 인수로 lvalues을 요구 기능을 사용해야 할 때 유용하지만 당신이 그 특정 값이 무엇을 얻을에 관심이없는 으로 바뀌었다. 다른 출력에 관심이있는 경우 주어진 특정 인수와 관련이없는 벡터입니다. 예를 들어

이 :

std::string get_my_file() { 
    return {std::istreambuf_iterator<char>(lvalue(std::ifstream("myfile.txt"))), 
      {}}; 
} 

그리고이 :

std::string temp1 = get_my_shader(); 
const char *temp2 = temp1.c_str(); 
glShaderSource(a, 1, &temp2, nullptr); 

이 변경 될 수

std::string get_my_file() { 
    std::ifstream ifs("myfile.txt"); 
    return {std::istreambuf_iterator<char>(ifs), {}}; 
} 

이 변경 될 수

glShaderSource(a, 1, &lvalue(get_my_shader().c_str()), nullptr); 
,691,363 이 같은210

그리고 수 일 :

void foo(int *x) { 
    std::cout << *x << std::endl; 
} 

foo(&lvalue(5)); 
내가 어떤 표시되지 않기 때문에이있을 수 있지만, 나는이 모든에 정의되지 않은-동작을 호출하거나 아니에요 여부를 확인하고 싶습니다

그것을 불법으로 만드는 캐스팅 규칙 (무시해도 됨). 임시 직원의 수명과 관련하여 AFAIK, rvalues live until the end of full-expression 및 그 기능의 사용이 이에 국한되어 있으므로 문제가 발생하지 않습니다.

이 주제에 될 것으로 보인다 reinterpret_castxvalues 에 대한 표준에 최근 변화가있다 :

https://stackoverflow.com/a/26793404/1000282

편집 : 붕괴 참조를 사용

더 나은 버전이 제안 :

template <typename T> 
constexpr T &lvalue(T &&r) noexcept { return r; } 
+0

괜찮습니다. xvalues를 lvalues로 캐스팅하면 더 쉽게 작업을 수행 할 수있는 유일한 문제는 평생 문제이며, 임시 인스턴스가 생성 문을 넘어서 참조되지 않으므로 예제에는 아무런 위험이 없습니다. ('reinterpret_cast'-proposal은 실제로 당신의 질문에 영향을 미치지 않습니다.) – Deduplicator

+0

@Deduplicator 고맙습니다. 질문에'& lvalue (5)'와 같은 표현이 포함되어 있기 때문에 특별히 xvalues가 아닌 rvalues를 사용했습니다. 어느 것이 잘 작동하는지. –

+1

현재 : 왜 참조 축소 규칙 대신에'std :: remove_reference_t'를 사용합니까? – Deduplicator

답변

9

당신이 말했듯이 임시 주인에 대한 포인터 나 참조가 그들의 범위를 벗어나지 않도록주의를 기울였습니다.
lvalue -function (내 이름 : no_move)을 사용하면 부주의하게 쉽게 해당 협착을 깨뜨릴 수 있습니다.

다음은 xvalues이 무엇인지 살펴 보겠습니다. 개체는 만료되지만 개체는 만료됩니다.
이것은 그들이 장례식 여행 중임을 무시할 수 있음을 의미합니다 (사용자가 기능을 사용하도록 요청하지 않는 한 해당 기능을 자연스럽게 수행합니다).

마지막으로 언급 한 점은 prvalue를 호출하는 것이 었습니다. 가장 중요한 것은 객체가 아닙니다.
그러나 함수를 호출 할 때와 같이 문제가되지는 않지만 임시 요소가 만들어집니다.
일시적으로 자연스럽게 성명의 끝까지 살아남습니다.

제쳐두고 std::remove_reference_t<T>&을 사용하면 반환 유형이 lvalue 인 경우 불필요하므로 T&을 직접 사용할 수 있으며 참조 축소 규칙을 사용합니다. 또한 static_castinline은 불필요합니다.

template <typename T> constexpr T& lvalue(T&& r) noexcept {return r;}