C++模板专用化:更改运算符()的返回类型
C++ template specialization: change return type of operator()?
在下面的类中,我定义了一个返回return_T
向量的operator()
:
#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()
编写第二个类,但我很好奇是否也可以用一个类来完成。所以我的问题是:这可能吗?
#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>{}, "!");
}
DEMO
您可以创建一个专门化的"traits"类,而不是专门化A
:
template <typename return_T>
struct Traits {
using ReturnType = std::vector<return_T>;
};
template <>
struct Traits<void> {
using ReturnType = void;
}
template <typename return_T, typename ... arg_T>
class A
{
public:
typename Traits<return_T>::ReturnType operator()(arg_T... args);
};
这样你就不必专门化A
,如果A
很大,并且专门化它会比专门化一个小的特征类更复杂,这会很方便。
相关文章:
- 为什么重载运算符可以返回其返回类型以外的其他内容?
- 错误:为"运算符 std::string {aka std::__cxx11::basic_string}"指定的返回类型<char>
- 运算符和返回类型是什么意思?
- 为什么类的赋值运算符的返回类型通常是非常量(而不是常量)引用?
- 重载运算符返回什么类型的值(对于用户定义的类型):右值还是左值?
- 如何确定三元运算符的返回类型?
- 范围分辨率运算符在类型:: var的情况下返回什么
- 如何使模板化运算符推断出正确的返回类型
- 重载常量和非常量转换运算符返回数组类型时出现 MSVC 错误 C2593
- 根据运算符推断模板返回类型:结果
- 重写运算符的返回类型=
- 错误:"运算符="不匹配 |结构返回类型
- 我无法让这个虚拟模板化函子运算符返回正确的类型
- 使用 std::function 时选择自动返回类型而不是构造函数的调用运算符
- 条件运算符的返回类型和两阶段查找
- 如何使用内置返回类型重载运算符?
- 分配运算符的返回类型
- C++关于引用运算符返回类型的基本概念
- C++移动分配运算符返回类型
- 算术运算符返回类型