2016-09-28 16 views
5

Xét đoạn mã sau:decltype (tự động), loại trả về theo sau và sfinae: chúng ta có thể trộn chúng không?

auto f() -> decltype(auto) { /* do whatever you want here */ } 
int main() { f(); } 

Các kiểu trả về là suy luận và decltype(auto) được sử dụng như trailing kiểu trả về.
Đoạn code dưới đây là một chút thay đổi (trên thực tế, sfinae'd) phiên bản:

struct S { static void f() {} }; 
struct T {}; 

template<typename U> 
auto f(int) -> decltype(U::f(), void()) { 
    // do whatever you want here 
} 

template<typename> 
auto f(char) -> decltype(auto) { 
    // do whatever you want here 
} 

int main() { 
    f<S>(0); 
    f<T>(0); 
} 

Nếu bạn đi trong kỳ thi chức năng này:

template<typename U> 
auto f(int) -> decltype(U::f(), void()) { 
    // do whatever you want here 
} 

Câu hỏi đặt ra là: là nó có thể sử dụng kiểu trả về đuôi để làm sfinae và vẫn có kiểu trả về được suy ra?
Ý tôi là một cái gì đó giống như mã dưới đây (đó không làm việc, tất nhiên):

template<typename U> 
auto f(int) -> decltype(U::f(), auto) { 
    // do whatever you want here 
} 

Lưu ý: Tôi không tìm kiếm các phương pháp thay thế liên quan đến các thông số mẫu, tôi biết chúng và tôi m chỉ tò mò muốn biết nếu này là một giải pháp khả thi.

+1

Đừng nghĩ rằng có thể nhưng bạn muốn loại được suy ra là 'tự động' hoặc là' decltype (tự động) '? – Holt

+0

Đừng nghĩ rằng có bất cứ điều gì bạn có thể làm ở đây. Các loại trả lại cố ý không có nghĩa là SFINAE. – Xeo

+0

@ Holt Câu hỏi hay, tôi đã nói 'decltype (tự động) 'như trong ví dụ đầu tiên, nhưng nếu bạn biết làm thế nào để có nó suy ra như' tự động' nó có thể là một câu trả lời tốt là tốt. – skypjack

Trả lời

4

decltype(auto) là một cấu trúc không thể tách rời (gần như là một từ khóa như decltype_auto). Ngoài ra, không thể sử dụng auto làm thực thể độc lập bên trong decltype(x), vì điều đó sẽ ngăn không cho x là biểu thức hợp lệ.

0

Không phải là câu trả lời, nhưng có thể giải quyết bằng cách sử dụng void_t.

Ít nhất đó là như khô như những gì bạn muốn làm:

template<typename... Ts> struct make_void { typedef void type;}; 
template<typename... Ts> using void_t = typename make_void<Ts...>::type; 


struct S { static int f() { return 3; } }; 
struct P { static int p() { return 4; } }; 
struct T {}; 

template<typename U, void_t<decltype(U::f())>* = nullptr > 
auto f(int) -> decltype(auto) 
{ 
    // do whatever you want here 
    std::cout << "f1\n"; 
    return U::f(); 
} 

template<typename U, void_t<decltype(U::p())>* = nullptr > 
auto f(int) -> decltype(auto) 
{ 
    // do whatever you want here 
    std::cout << "f3\n"; 
    return U::p(); 
} 

template<typename> 
auto f(char) -> decltype(auto) { 
    std::cout << "f2\n"; 
    // do whatever you want here 
} 

int main() { 
    std::cout << f<S>(0) << '\n'; 
    std::cout << f<P>(0) << '\n'; 
    f<T>(0); 
} 
0

Bạn có thể thêm một tham số có kiểu void(*)() đến chức năng và chỉ định một lambda với trailing kiểu trả về để nó như là một đối số mặc định để SFINAE có thể được áp dụng qua lambda:

template<typename U> 
decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {}) 
{ 
    // do whatever you want here 
} 
Các vấn đề liên quan