在下面的类中我定义了一个 operator()
返回 return_T
的 vector :
#include <vector>
template <typename return_T, typename ... arg_T>
class A
{
public:
std::vector<return_T> operator()(arg_T... args);
};
这有效,除了 return_T = void
的情况, 因为 vector<void>
是不可能的。所以我需要定义 A<void, arg_T>::operator()
的特化不知何故。我正在试验以下代码:
#include <vector>
template <typename return_T, typename ... arg_T>
class A
{
public:
auto operator()(arg_T... args);
};
template<typename return_T, typename... arg_T>
auto A<return_T, arg_T...>::operator()(arg_T... args) -> typename std::enable_if<!std::is_void<return_T>::value, std::vector<return_T>>::type
{ }
template<typename return_T, typename... arg_T>
auto A<void, arg_T...>::operator()(arg_T... args) -> void
{ }
但是编译器不喜欢它。
error : prototype for 'typename std::enable_if<(! std::is_void<_Tp>::value), std::vector<_Tp> >::type A<return_T, arg_T>::operator()(arg_T ...)' does not match any in class 'A<return_T, arg_T>'
auto A<return_T, arg_T...>::operator()(arg_T... args) -> typename std::enable_if<!std::is_void<return_T>::value, std::vector<return_T>>::type
error : candidate is: auto A<return_T, arg_T>::operator()(arg_T ...)
auto operator()(arg_T... args);
^
error : invalid use of incomplete type 'class A<void, arg_T ...>'
auto A<void, arg_T...>::operator()(arg_T... args) -> void
^
当然,我可以用 void operator()
轻松编写第二个类,但我很好奇是否也可以用一个类(class)来完成。那么我的问题是:这可能吗?
最佳答案
#include <type_traits>
#include <utility>
#include <vector>
template <typename return_T, typename... arg_T>
class A
{
public:
auto operator()(arg_T... args)
{
return invoke(std::is_void<return_T>{}, std::forward<arg_T>(args)...);
}
private:
void invoke(std::true_type, arg_T&&... args)
{
}
std::vector<return_T> invoke(std::false_type, arg_T&&... args)
{
return {};
}
};
测试:
int main()
{
A<int, char, short> a;
static_assert(std::is_same<decltype(a('x', 5)), std::vector<int>>{}, "!");
A<void, char, short> b;
static_assert(std::is_same<decltype(b('x', 5)), void>{}, "!");
}
关于C++ 模板特化 : change return type of operator()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33469666/