仿函数运算符的有条件特化()

时间:2016-08-19 10:16:41

标签: c++ c++11 functor template-specialization enable-if

我想请你帮忙解决我最近几天遇到的编程问题。让我试着解释一下我将要实施的内容......

我的目标是定义一组有效性的方程式。让我详细解释一下......

我认为每个方程对象都是一个仿函数 - 一个定义operator()的类。此运算符的定义应专用于每个方程类型。专业化包含计算本身:

·H:

enum class IDs : int { A = 0, B = 1, C = 2 };

template<IDs WHICH>
struct Equation
{
    int operator() ( void );
}

的.cpp:

template<>
Equation<IDs::A>::operator()( void )
{
    /* Just some sample equation */
    return( 42 + 28 );
}

您可能已经注意到,专门化由枚举类成员ID ::?。

定义

这似乎有效。但我想添加所谓的可用性功能 - 该等式可能仅对某些用户对象类型有效。

There is 'validity group' declared:
/* Object types declaration */
namespace Objects {
    using Object0 = boost::mpl::int_<0>;
    using Object1 = boost::mpl::int_<1>;
    using Object2 = boost::mpl::int_<2>;
}
/* Validity groups declaration */
using ValidityGroup1 = boost::mpl::vector<Object0, Object2>;
using ValidityGroup2 = boost::mpl::vector<Object1>;

我使用以下构造来启用或禁用类(使用boost :: enable_if)。只是为了说明我如何使用它:

template<typename TYPE_LIST, typename QUERY_TYPE>
struct IsTypeInList
{
    using TypePos    = typename boost::mpl::find<TYPE_LIST, QUERY_TYPE>::type;
    using Finish     = typename boost::mpl::end<TYPE_LIST>::type;
    using type       = typename boost::mpl::not_<boost::is_same<TypePos, Finish> >::type;
    using value_type = typename type::value_type;

    static const bool value = type::value;
};

template<typename OBJECT_TYPE, typename ENABLER=void>
class SampleClass;

template<typename OBJECT_TYPE>
class SampleClass<OBJECT_TYPE, typename boost::enable_if<typename IsTypeInList<ValidityGroup1, Object0>::type>::type>
{}

仅当Object0属于ValidityGroup1时,才能使用SampleClass的部分特化。到现在为止还挺好。这个原则得到了验证。

现在有趣的东西来了。我想把这两件事合并在一起:

目标:

定义方程式运算符()包含有效正文的专业化是由ID :: ??定义的枚举类值&#34;并且仅适用于属于ValidityGroup的对象...可以有相同ID的另一个计算:: ??但对其他ValidityGroup中的Object有效(又名Object0&#39; s属性是以不同于Object1的方式计算的)

我知道整个概念非常复杂,可能令人困惑。让我展示我尝试实现这些东西:

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID, typename ENABLER = void>
class Equation;

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
class Equation<OBJECT_TYPE, VALIDITY_GROUP, ID, typename boost::enable_if<typename IsTypeInList<VALIDITY_GROUP, OBJECT_TYPE>::type>::type >
:   public EquationBase<IDs>
{
public:
int operator() ( void );
};

template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
int Equation<OBJECT_TYPE, ValidityGroup1, Ids::A>::operator() ( void )
{
    return( 42 + 56 );
}

但是operator()定义不起作用......你能告诉我如何使这个工作吗?或者有没有人知道如何实现上述目标?

非常感谢提前给任何愿意帮助我的人......

干杯马丁

编辑: 该等式用于模板类对象。让代码解释一下:

template<typename OBJECT_TYPE>
class Object
{
public:
    Object( void );
};

的.cpp:

template<typename OBJECT_TYPE>
Object<OBJECT_TYPE>::Object( void )
{
    std::cout << Equation<IDs::A>()() << std::endl;
}

问题是当operator()是专门的时,没有定义OBJECT_TYPE ......

1 个答案:

答案 0 :(得分:1)

如果我理解你想要获得什么,我想有很多方法。

以下是一个简单的示例(但完整的广告工作),展示了如何使用std::enable_if选择不同的实现(但boost::enable_if应该没问题)和运算符的返回类型

#include <iostream>
#include <type_traits>

template <typename ObjT, typename ValT>
class Equation
 {
   public:
      template <typename X = ObjT>
         typename std::enable_if<true == std::is_same<X, ValT>::value, int>::type
         operator() ( void )
          { return( 0 ); }

      template <typename X = ObjT>
         typename std::enable_if<false == std::is_same<X, ValT>::value, int>::type
         operator() ( void )
          { return( 1 ); }
 };

int main()
 {
   Equation<int, int>  eq0;
   Equation<int, long> eq1;

   std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
   std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
 }

我认为并不是很优雅。

另一种解决方案(我认为,最适合您的需求)可能是基于类部分专业化的以下内容

#include <iostream>
#include <type_traits>


template <typename ObjT, typename ValT, bool = std::is_same<ObjT, ValT>::value>
class Equation;

template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, true>
 {
   public:
      int operator() ();
 };

template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, false>
 {
   public:
      int operator() ();
 };


template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, true>::operator() ()
 { return( 0 ); }

template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, false>::operator() ()
 { return( 1 ); }

int main()
 {
   Equation<int, int>  eq0;
   Equation<int, long> eq1;

   std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
   std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
 }