c++ - 检查方法的模板特化是否存在

标签 c++ templates c++14 sfinae

假设我有一个这样的模板类:

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 提供一个默认的空实现,如果它不是专门的,则会调用一个空方法。我想知道是否有更好的方法。

最佳答案

Currently my workaround is giving a default empty implementation to validate_core, if it's not specialized then an empty method is invoked. I want to know if there is a better way.

在我看来这是一个很好的方法。

不确定是否理解您的要求,但我想您可以删除 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/disabled) 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); }

否则(也许更好一点)一些基于标签分派(dispatch)的东西

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>{}); }

恕我直言,基于 validate_core() 的空泛型版本的解决方案(在 C++14 中)更好。

无论如何,下面是一个完整的工作示例

#include <iostream>
#include <type_traits>

template <typename TRequest, typename TResponse = void>
class handler
 {
   private:
      template <typename TRq = TRequest>
      static void validate_core (TRequest const &) = delete;

      static void validate_core (int const &)
       { std::cout << "- validate_core() int case" << std::endl; }

      static void validate_core (long const &)
       { std::cout << "- validate_core() long case" << std::endl; }

      static TResponse process_core (const TRequest &)
       { return TResponse(); }

      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
       { };

   public:
      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); }
 };

int main()
 {
   handler<int>::process(0);        // print - validate_core() int case
   handler<int, long>::process(0);  // print - validate_core() int case
   handler<long>::process(0);       // print - validate_core() long case
   handler<char>::process(0);       // no print
 }

关于c++ - 检查方法的模板特化是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47747271/

相关文章:

c++ - 使用static_cast创建的枚举调用C++函数的安全性

c++ - 动态创建一个新的 protobuf 消息

带有参数的 C++ 模板策略

c++ - 从 Istringstream 管道到模板

c++ - 是直接初始化还是复制初始化?

c++ - 继承依赖的 typedef 而不使用 struct

c++ - 命令行参数、cant 或两个变量

c++ - 模板特化错误 - C++(C++ Primer Plus 练习)

c++ - 根据模板参数添加成员函数和成员变量

c++ - boost optional 和 std::experimental optional assignment 之间的区别