2016-09-28 101 views
5

考虑下面的代码:decltype(auto),追踪返回类型和sfinae:我们可以混合它们吗?

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

返回类型推导并decltype(auto)用作后返回类型。
下面的代码是一个稍微修改的(实际上,sfinae'd)版本:

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

如果你在考试采取这样的功能:

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

的问题是:是否有可能使用尾随返回类型来做sfinae并且仍然具有推导出的返回类型?
我的意思是像下面的代码(不工作,当然):

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

注:我不是在寻找涉及模板参数的替代方法,我知道他们和我”米只是好奇,知道如果是一个可行的解决方案。

+1

不要以为这是可能的,但你想要的类型推断为'auto'或者'decltype(auto)'? – Holt

+0

不要以为这里有什么可以做的。特意扣除退货类型不要SFINAE。 – Xeo

+0

@Holt好问题,我会说在第一个例子中有'decltype(auto)',但是如果你知道如何将它推断为'auto',它也可以是一个很好的答案。 – skypjack

回答

4

decltype(auto)是一个不可分割的结构(就好像它是一个像decltype_auto这样的关键字)。除此之外,auto不能用作decltype(x)中的独立实体,因为这会阻止x成为有效的表达式。

0

不是答案,而是使用void_t的可能解决方法。

至少它干成你想要做什么:

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

可以void(*)()类型的其他参数,将其作为默认参数,因此SFINAE添加的功能和分配尾随返回类型的拉姆达可以通过拉姆达应用:

template<typename U> 
decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {}) 
{ 
    // do whatever you want here 
} 
相关问题