根据模板方法中不同类型的不同代码路径
Different code path according to different type in a template method
假设我有一个这样的模板class:
template<typename TRequest, typename TResponse = void>
class handler
{
private:
TResponse process_core(const TRequest& request);
public:
TResponse process(const TRequest& request)
{
//log the request
TResponse response = process_core(request); //return process_core(request) works;
//log the response, for void it's fine to log nothing
return response;
}
};
项目中的其他地方 process_core
是为不同的 TRequest/TResponse 类型实现的。例如:
template<> void handler<Foo>::process_core(const Foo& foo) { }
template<> Baz handler<Bar, Baz>::process_core(const Bar& bar) { }
显然 return response
中断 void
类型。执行此操作的正确方法是什么?或者我的设计不是 C++ 方式?我是 C++ 新手。
不幸的是 void
不是常规类型,尽管有一个旨在修复 ("regular void" by Matt Calabrese) 的提案,因此您需要处理它以一种特殊的方式。使用 C++17,您可以简单地使用 if constexpr(...)
在编译时进行分支:
TResponse process(const TRequest& request)
{
TResponse response = process_core(request);
// ...
if constexpr(!std::is_same_v<TResponse, void>)
{
return response;
}
}
使用 C++11/14,您可以使用标签调度:
TResponse process(const TRequest& request)
{
return processImpl(request, std::is_same<TResponse, void>{});
}
void process(const TRequest& request, std::true_type /* void */)
{
TResponse response = process_core(request);
// ...
}
TResponse process(const TRequest& request, std::false_type /* not void */)
{
TResponse response = process_core(request);
// ...
return response;
}
或者,您可以将 void
转换为常规 nothing
类型并对其进行均匀处理。
struct nothing { };
template <typename T>
struct void_to_nothing { using type = T; };
template <>
struct void_to_nothing<void> { using type = nothing; };
template <typename T>
using void_to_nothing_t = typename void_to_nothing<T>::type;
auto process(const TRequest& request)
{
void_to_nothing_t<TResponse> response = process_core(request);
// ...
return response;
}
请注意,在这种情况下,process_core
必须 return nothing
而不是 void
,因此您无论如何都需要某种专业化或编译时分支。
假设我有一个这样的模板class:
template<typename TRequest, typename TResponse = void>
class handler
{
private:
TResponse process_core(const TRequest& request);
public:
TResponse process(const TRequest& request)
{
//log the request
TResponse response = process_core(request); //return process_core(request) works;
//log the response, for void it's fine to log nothing
return response;
}
};
项目中的其他地方 process_core
是为不同的 TRequest/TResponse 类型实现的。例如:
template<> void handler<Foo>::process_core(const Foo& foo) { }
template<> Baz handler<Bar, Baz>::process_core(const Bar& bar) { }
显然 return response
中断 void
类型。执行此操作的正确方法是什么?或者我的设计不是 C++ 方式?我是 C++ 新手。
不幸的是 void
不是常规类型,尽管有一个旨在修复 ("regular void" by Matt Calabrese) 的提案,因此您需要处理它以一种特殊的方式。使用 C++17,您可以简单地使用 if constexpr(...)
在编译时进行分支:
TResponse process(const TRequest& request)
{
TResponse response = process_core(request);
// ...
if constexpr(!std::is_same_v<TResponse, void>)
{
return response;
}
}
使用 C++11/14,您可以使用标签调度:
TResponse process(const TRequest& request)
{
return processImpl(request, std::is_same<TResponse, void>{});
}
void process(const TRequest& request, std::true_type /* void */)
{
TResponse response = process_core(request);
// ...
}
TResponse process(const TRequest& request, std::false_type /* not void */)
{
TResponse response = process_core(request);
// ...
return response;
}
或者,您可以将 void
转换为常规 nothing
类型并对其进行均匀处理。
struct nothing { };
template <typename T>
struct void_to_nothing { using type = T; };
template <>
struct void_to_nothing<void> { using type = nothing; };
template <typename T>
using void_to_nothing_t = typename void_to_nothing<T>::type;
auto process(const TRequest& request)
{
void_to_nothing_t<TResponse> response = process_core(request);
// ...
return response;
}
请注意,在这种情况下,process_core
必须 return nothing
而不是 void
,因此您无论如何都需要某种专业化或编译时分支。