【问题标题】:Conditional specialization of functors operator()函子 operator() 的条件特化
【发布时间】:2016-08-19 10:16:40
【问题描述】:

我想请你帮忙解决我最近几天遇到的编程难题。让我试着解释一下我将要实现什么......

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

我认为每个方程对象都是函子 - 一个定义 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 );
}

您可能已经注意到,特化是由枚举类成员 IDs::? 定义的。

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

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 的部分特化才可用。到目前为止,一切都很好。这个原理得到验证。

现在有趣的事情来了。我想将这两件事合并在一起:

目标:

Define Equation 的 operator() 包含有效主体的特化由 IDs::?? 定义枚举类值”并且仅适用于属于 ValidityGroup 的对象... 可以有另一个相同 ID 的计算::?? 但对其他 ValidityGroup 中的对象有效(又名 Object0 的属性的计算方式不同于 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;
}

问题是在运算符()专门化时没有定义OBJECT_TYPE...

【问题讨论】:

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


    【解决方案1】:

    如果我理解正确你想得到什么,我想有很多方法。

    以下是一个 iper 简化示例(但完整的广告工作),展示了如何使用 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"
     }
    

    【讨论】:

    • 非常感谢 Max66!我会等 :o) 期待看看。也许还需要考虑一件事......方程归一个类所有,该类也是模板化的,根据所有者对象模板参数选择正确的 operator() 实现会很棒......请参阅我的原始帖子中的编辑...
    • @MartinKopecký - 添加了另一个示例;抱歉,您的“类似:”是您评论的最后一部分;我不明白你想要什么;我认为如果您修改问题或(如果您的下一个需求确实不同)插入另一个问题会更好
    • 对不起,我编辑原始帖子的速度很慢...非常感谢您的努力,我将分析您的代码以查看是否合适...我尝试了很多变体,所以我感觉有点现在对我的话题感到困惑...... :o)
    • @MartinKopecký - “问题是当运算符 () 是专门的时,OBJECT_TYPE 没有定义......”......我想这不是问题,但你应该准备一个简化和完整的(如果可能)示例。
    • @MartinKopecký - 抱歉:我的第一个示例不完整(复制和粘贴错误):缺少main()(等于第二个示例);更正
    猜你喜欢
    • 1970-01-01
    • 2014-01-30
    • 2021-12-14
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 2022-12-06
    • 2021-05-13
    • 2018-08-21
    相关资源
    最近更新 更多