【问题标题】:Specialise functor when template class is_convertible to a well known type当模板类 is_convertible 为众所周知的类型时特化函子
【发布时间】:2015-09-20 03:09:41
【问题描述】:

所以我想在模板类型boost::is_convertibleWellKnownType 时应用特定代码:

template <typename T>
class Foo {
public:
    Foo() {
        // apply specific function to m_t
        // if T is convertible to WellKnownType
    }
    T m_t;
};

为此,我考虑过使用仿函数:

template <typename T>
struct my_functor {
    void operator()(T& t) {
        // do nothing by default
    }
};

那么,当boost::is_convertible&lt;T, WellKnownType&gt;:

template <>
struct my_functor<...> {
    void operator()(T& t) {
        // do something to t because it is convertible to WellKnownType 
    }
};

然后,我想我可以轻松地将Foo 的定义更改为使用函子,并在T 可转换为WellKnownType 时执行某些操作,而当它不是时则不执行任何操作:

template <typename T>
class Foo {
public:
    Foo() {
        my_functor<T>()(m_t);
    }
    T m_t;
};

我不知道如何实现这种行为。我知道BOOST_CONCEPT_REQUIRES,但不知道如何将其应用于模板专业化。有什么帮助吗?

【问题讨论】:

    标签: c++ c++11 boost c++-concepts c++17


    【解决方案1】:

    您可以使用仿函数执行以下操作

    template<typename T, typename WellKnownType >
    struct my_functor
    {
        void operator()( const T& x) { 
           myopImpl(x, boost::is_convertible<T, WellKnownType>() ); 
        }
    
        void  myopImpl(T const& x, boost::false_type) 
        {  std::cout << "Some Other Stuff \n";  }
    
        void  myopImpl(T const& x, boost::true_type)  
        { std:: cout << "Some Specific Stuff \n";  }
    
    };
    

    Demo here

    【讨论】:

    • 就可以了。谢谢!
    【解决方案2】:

    由于您标记了这个 C++11,您应该使用标准库类型特征而不是 Boost 特征。此外,您可以部分专注于类型特征 - 它只需要是另一个模板参数:

    template<typename T, typename WellKnownType, typename = void>
    struct my_functor
    {
        void operator()(T const& x) { 
            // generic code  
        }
    };
    
    template <typename T, typename WellKnownType>
    struct my_functor<T, WellKnownType,
        std::enable_if_t<std::is_convertible<T, WellKnownType>::value>
        >
    {
        void operator()(T const& x) {
            // specific code if convertible
        }
    };
    

    如果您不喜欢第三个参数的外观,您可以将其放在命名空间中,然后简单地添加:

    template <typename T, typename WellKnownType>
    using my_functor = details::my_functor<T, WellKnownType>;
    

    或者,您可以使用类型特征为两个完全不相关的仿函数类型之一设置别名:

    template <typename T, typename WellKnownType>
    using my_functor = std::conditional_t<
        std::is_convertible<T, WellKnownType>::value,
        my_functor_specific<T>,
        my_functor_generic<T>>; 
    

    【讨论】:

      【解决方案3】:

      为了完整起见,进行了一些研究,我最终也使用 std::enable_ifstd::is_base_of 选择了这个选项:

      template <typename T>
      void do_it( typename std::enable_if<std::is_base_of<WellKnownType, T>::value, T>::type& t )
      {
          std::cout << "Specific code\n";
      }
      
      ...
      
      template <typename T>
      void do_it( typename std::enable_if<!std::is_base_of<WellKnownType, T>::value, T>::type& t )
      {
          std::cout << "Generic code\n";
      }
      

      【讨论】:

      • 如果你真的尝试过这个,你会发现它不起作用。 T 处于非推断上下文中。
      • 我将其作为免费功能进行了尝试,确实如此,我将更改代码以确保安全。谢谢。
      • 当然,如果你明确指定类型,如果它是一个正常的函数,那是可以的,但对于operator(),这很可笑。
      猜你喜欢
      • 1970-01-01
      • 2021-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多