我们说我有一个这样的模板类:
template<typename TRequest, typename TResponse = void>
class handler
{
private:
static void validate_core(const TRequest& request);
static TResponse process_core(const TRequest& request);
public:
static TResponse process(const TRequest& request)
{
if (validate_core is implemented)
{
log("begin validate");
validate_core(request);
}
return process_core(request);
}
};
process_core
必须针对不同的TRequest / TResponse类型实现,而validate_core
是可选的,我想在实现时调用它。
目前,我的解决方法是向validate_core
提供默认的空实现,如果它不是专用的,则调用空方法。我想知道是否有更好的方法。
答案 0 :(得分:0)
如果实现模板专业化,则无法在编译时检查。最好通过声明和外部模板实例化来生成链接时错误。
我理解你希望process
实现所谓的模板方法设计模式。如果是这种情况,您可能会发现以下CRTP的使用很有意思。 (Nota bene:我修改了函数签名以使这段代码可编辑)
template<class Derived, typename TRequest, typename TResponse>
class handler_base
{
private:
//caution trickery
static constexpr bool validate_core=false;
public:
static TResponse* process(const TRequest& request)
{
if constexpr (Derived::validate_core)
{
//log("begin validate");
Derived::validate_core(request);
}
return Derived::process_core(request);
}
};
template<typename TRequest, typename TResponse=void>
class handler;
class Req1;
class Req2;
class Resp1;
class Resp2;
template<>
class handler<Req1,Resp1>
: handler_base<handler<Req1,Resp1>,Req1,Resp1>
{
static void validate_core(const Req1& request);
static Resp1* process_core(const Req1& request);
friend handler_base;
};
template<>
class handler<Req2,Resp2>
: handler_base<handler<Req2,Resp2>,Req2,Resp2>
{
friend handler_base;
static Resp2* process_core(const Req2& request);
};
//just to force compilation
template Resp2* handler_base<handler<Req2,Resp2>,Req2,Resp2>::process(const Req2&);
template Resp1* handler_base<handler<Req1,Resp1>,Req1,Resp1>::process(const Req1&);
答案 1 :(得分:-1)
目前我的解决方法是为validate_core提供一个默认的空实现,如果它不是专用的,则调用一个空方法。我想知道是否有更好的方法。
在我看来,这是一个非常好的方式。
不确定您的要求,但我想您可以删除validate_core()
template <typename TRq = TRequest>
static void validate_core (TRequest const &) = delete;
并在handler
的正文内启用一个或多个非模板专精
static void validate_core (int const &)
{ /* do something */ }
static void validate_core (long const &)
{ /* do something */ }
// ...
接下来,您可以在handler
的正文中添加一个类型特征,以检测它是否可用于validate_core()
template <typename, typename = void>
struct withValidateCore : public std::false_type
{ };
template <typename T>
struct withValidateCore<T, decltype(validate_core(std::declval<T>()))>
: public std::true_type
{ };
如果您可以使用C ++ 17,这种方式可能会很有趣,因为它可用if constexpr ()
,所以应该可以这样做[抱歉:未经测试]
static TResponse process (TRequest const & request)
{
if constexpr ( withValidateCore<TRequest>::value )
{
log("begin validate");
validate_core(request);
}
return process_core(request);
}
但您标记了C ++ 14,因此if constexpr ()
不可用,我看到使用withValidateCore
的最佳方式是实现两个不同的(SFINAE启用/禁用)版本的{{ 1}};
process()
否则(可能会好一点)基于标签调度的东西
template <typename TRq = TRequest>
static std::enable_if_t<(true == withValidateCore<TRq>{})
&& (true == std::is_same<TRq, TRequest>{}), TResponse>
process (TRequest const & request)
{
validate_core(request);
return process_core(request);
}
template <typename TRq = TRequest>
static std::enable_if_t<(false == withValidateCore<TRq>{})
&& (true == std::is_same<TRq, TRequest>{}), TResponse>
process (TRequest const & request)
{ return process_core(request); }
恕我直言,基于空private:
static TResponse process (TRequest const & request,
std::true_type const &)
{
validate_core(request);
return process_core(request);
}
static TResponse process (TRequest const & request,
std::false_type const &)
{ return process_core(request); }
public:
static TResponse process (TRequest const & request)
{ return process(request, withValidateCore<TRequest>{}); }
的通用版本的解决方案更好(在C ++ 14中)。
无论如何,以下是一个完整的工作示例
validate_core()