2011-10-01 43 views
11

Tôi vừa xem this really nice talkĐá cứng: C++ Phát triển bởi Boris Jabes. Trong phần của cuộc nói chuyện liên quan đến bậc cao Generic Lập trình ông nói rằng sau đây là một ví dụ về một hàm đó là chung chung hơn là liên quan đến kiểu trả về của nó và dẫn đến ít mẫu chức năng quá tảiCách sử dụng khai sáng của C++ 11 decltype

template <typename Func> 
auto deduce(const Func & f) -> decltype(f()) 
{..} 

này Tuy nhiên có thể được thực hiện sử dụng mẫu cú pháp đơn giản như sau

template <typename Func> 
Func deduce(const Func & f) 
{..} 

vì vậy tôi đoán ví dụ chọn không thực sự cho thấy sức mạnh độc đáo của decltype. Bất kỳ ai có thể đưa ra ví dụ về việc sử dụng làm sáng tỏ hơn của decltype?

+7

No. Ví dụ đầu tiên có nghĩa là '' 'deduce (f)' '' trả về loại kết quả '' 'Func'''. Ví dụ thứ hai có nghĩa là '' 'suy ra (f)' '' trả về '' 'Func'''. Bạn có thấy sự khác biệt? –

+0

Aah, xin lỗi tôi đã bỏ lỡ thêm '()' bên trong đối số cho 'decltype'. Lỗi của tôi. –

Trả lời

25

Nghi ngờ của bạn không chính xác.

void f() { } 

Bây giờ deduce(&f) có kiểu void, nhưng với viết lại của bạn, nó có kiểu void(*)(). Trong mọi trường hợp, ở mọi nơi bạn muốn nhận được loại biểu thức hoặc tuyên bố, bạn sử dụng decltype (lưu ý sự khác biệt tinh tế giữa hai loại này. decltype(x) không nhất thiết phải giống như decltype((x))).

Ví dụ, nó có khả năng tiêu chuẩn thư viện thực hiện của bạn ở đâu đó có chứa đường như

using size_t = decltype(sizeof(0)); 
using ptrdiff_t = decltype((int*)0 - (int*)0); 
using nullptr_t = decltype(nullptr); 

Tìm hiểu các kiểu trả về đúng add đã là một vấn đề khó khăn trong suốt quá khứ C++. Đây là một bài tập dễ dàng.

template<typename A, typename B> 
auto add(A const& a, B const& b) -> decltype(a + b) { return a + b; } 

Ít được biết đến là bạn có thể sử dụng decltype trước :: và trong một tên giả destructor

// has no effect 
(0).~decltype(0)(); 

// it and ite will be iterators into an initializer list 
auto x = { 1, 2, 3 }; 
decltype(x)::iterator it = x.begin(), ite = x.end(); 
+1

Bạn có thể giải thích điều này một chút: '(0). ~ Decltype (0)();'? Tôi sợ tôi không hiểu. –

1
std::for_each(c.begin(), c.end(), [](decltype (c.front()) val){val*=2;}); 

Autodeducting các value_type của container c không thể được thực hiện mà không decltype.

+1

Nó không thể được thực hiện chỉ khi bạn đang sử dụng lambdas, cho rằng họ không phải là đa hình (chưa, chúng ta hãy hy vọng họ đang ở trong C + + y). Nếu bạn đang sử dụng một đối tượng hàm đa hình, nó sẽ được suy luận tự động. –

0

Một nơi mà tôi sử dụng nó, là nơi tôi cần phải thực hiện một biến mà phải có cùng loại của một biến khác. nhưng tôi không chắc liệu trong tương lai, loại hình này có giữ nguyên hay không.

void foo(int a)//maybe in future type of a changed 
{ 
    decltype(a) b; 
    //do something with b 
} 
Các vấn đề liên quan