2014-11-21 14 views
14

Recently I've discovered đôi khi có thể biến các giá trị tạm thời thành giá trị có thể là hữu ích cho tôi.Được xác định rõ ràng để đưa xvalues ​​vào giá trị để chuyển đến hàm?

Tôi đã sử dụng các công cụ sau:

#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); 
} 

Nó rất hữu ích khi bạn phải sử dụng chức năng yêu cầu lvalues ​​như tranh cãi, nhưng bạn không có bất cứ quan tâm đến những gì những người đặc biệt giá trị được biến thành. Khi bạn quan tâm đến các đầu ra khác vectơ không liên quan đến đối số cụ thể đã cho.

Ví dụ này:

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

có thể được thay đổi như sau:

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

Và đây:

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

có thể được thay đổi như sau:

glShaderSource(a, 1, &lvalue(get_my_shader().c_str()), nullptr); 

Và cho phép những điều như thế này:

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

foo(&lvalue(5)); 

Tôi muốn được chắc chắn cho dù tôi đang gọi không xác định-hành vi hay không trong những điều này, bởi vì tôi không thấy bất kỳ, mặc dù có thể có một số quy tắc đúc sẽ biến nó bất hợp pháp (mà tôi bỏ qua). Về tuổi thọ của thời gian, tôi không thấy vấn đề gì kể từ đó, AFAIK, rvalues live until the end of full-expression và việc sử dụng chức năng bị hạn chế.

Có một sự thay đổi gần đây với tiêu chuẩn về reinterpret_castxvalues rằng có vẻ là về chủ đề:

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

EDIT:

Better phiên bản sử dụng tài liệu tham khảo sụp đổ như đề xuất:

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

Bạn vẫn ổn. Điều duy nhất mà bạn có thể dễ dàng vít lên bằng cách đúc xvalues ​​để lvalues ​​là vấn đề suốt đời, và bạn là đúng không có nguy hiểm trong ví dụ của bạn, như tạm thời không được tham chiếu ngoài tuyên bố tạo ra nó. (Đề xuất 'reinterpret_cast' không thực sự chạm vào câu hỏi của bạn.) – Deduplicator

+0

@Deduplicator Cảm ơn, tôi đã nói giá trị thay vì xvalues ​​cụ thể, bởi vì câu hỏi cũng bao gồm các biểu thức như' & lvalue (5) '. Mà bằng cách này là làm việc tốt. –

+1

BTW: Tại sao bạn sử dụng 'std :: remove_reference_t' thay vì các quy tắc thu gọn tham chiếu? – Deduplicator

Trả lời

9

Như bạn đã nói, bạn cẩn thận không để bất kỳ con trỏ hoặc tham chiếu đến các thời gian thoát khỏi phạm vi của chúng.
Sử dụng số lvalue-chức năng của bạn (tên tôi được gọi là no_move) giúp dễ dàng phá vỡ sự nghiêm khắc đó một cách vô tình.

Tiếp theo, hãy xem những gì xvalues là: Vật thể hết hạn, nhưng đối tượng vẫn vậy.
Điều này có nghĩa, bạn có thể bỏ qua họ đang ở trong chuyến lưu diễn tang lễ của họ (nếu bạn chuyển chúng đến một hàm, chức năng đó sẽ tự động làm như vậy, trừ khi bạn yêu cầu tận dụng lợi thế).

Điểm cuối cùng bạn đã đề cập là gọi bằng giá trị gia tăng, điều này chắc chắn không phải là một đối tượng.
Nhưng ngay cả đó không phải là một vấn đề, như trên gọi chức năng, một tạm thời sẽ được tạo ra.
Và tạm thời đó cũng sẽ tự nhiên tồn tại vào cuối tuyên bố.

Ngoài việc sử dụng std::remove_reference_t<T>& là không cần thiết cho kiểu trả về lvalue, bạn có thể sử dụng trực tiếp T& và dựa vào quy tắc thu gọn tham chiếu. Ngoài ra, static_castinline là không cần thiết.

template <typename T> constexpr T& lvalue(T&& r) noexcept {return r;} 
Các vấn đề liên quan