2015-12-21 196 views
1

比方说,我有一个模板函数返回一个依赖类型。喜欢的东西:typedefing函数返回类型

template <class T> 
typename std::result_of<T()>::type 
foo() 
{ 
    std::result_of<T()>::type retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

正如你所看到的,我声明的返回值的局部变量时,曾在函数类型写的返回类型两次,一次,另一次。

有没有一种方法我可以typedef这种类型的函数签名,所以类型将只声明一次(无代码复制),并且只在函数(签名和正文)内可见和可用? 喜欢的东西(警告伪代码未来,请不要生气或启发!):

template <class T> 
typedef typename std::result_of<T()>::type FooReturnType 
FooReturnType foo() 
{ 
    FooReturnType retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

编辑:我是仅限于C++编译器11。

感谢

+0

尝试将其作为默认模板参数 – user3514538

+0

或者如果您的编译器支持C++ 14,可能是自动返回类型? – oLen

+0

@ user3514538想过它......但是然后调用者将能够覆盖此值。我需要'static_assert',第二个参数确实是我想要的(仍然需要写两次返回类型...):( –

回答

3
template <class T> 
typename std::result_of<T()>::type 
foo() 
{ 
    decltype(foo()) retVal; 
    // Some mind blowing code... 
    return retVal; 
} 
+1

如问,这是一个很好的解决方案。如果foo在现实中有很多复杂的论点,它不会那么好。但无论如何都要有一个赞成票。 –

2

正如评论说,有这种黑客:

template <class T, typename Ret = std::result_of_t<T()>> 
Ret foo() { 
    Ret retVal; 
    return retVal; 
} 

或者,你也许可以简单地使用返回类型推演,如果你的编译器是足够新:

template <class T> 
auto foo() { 
    std::result_of_t<T()> retVal; 
    return retVal; 
} 
+0

Thanks。请参阅我上面的注释。'auto'不存在问题(C++ 14功能)并且默认参数有点问题 –

+0

@user:那么你应该将这些要求添加到你的问题 –

+0

@NicolBolas你是对的...完成.. –

1

您可以使用设置为std::result_of<T()>::type的模板参数,如:

template <class T, class Ret = typename std::result_of<T()>::type> 
Ret foo() 
{ 
    Ret retVal = 100; 
    // Some mind blowing code... 
    return retVal; 
} 

Live Example

1

这是不是我们通过using允许模板的typedef?

template<typename T> 
using Ret = typename std::result_of<T()>::type; 

template<typename T> 
Ret<T> foo() 
{ 
    Ret<T> retVal; 
    // Some mind blowing code... 
    return retVal; 
} 

如果你不接受默认模板参数的传统C++ 98/03的解决方案,你会不会接受添加using别名到的C++ 11解决方案范围,并且你不能使用C++ 14解决方案的auto返回类型扣除,那么就没有解决方案。

+0

是的,但是包含此头文件的每个人都可以看到类型。正如我在问题中所说的,我更愿意避免这种情况... –

+0

我不喜欢这个解决方案的唯一的东西是它将'Ret'添加到全局范围。如果你想这样做与另一个,并希望'Ret'是不同的,你将不得不拿出另一个名字。 – NathanOliver

+2

@NathanOliver:然后将其粘贴到详细的命名空间或其他任何内容中。 –