涵盖const和非const方法的C ++模板 [英] C++ template to cover const and non-const method

查看:92
本文介绍了涵盖const和非const方法的C ++模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于复制 const 和非 const 版本的相同代码,我遇到了问题。我可以用一些代码来说明问题。这里有两个示例访问者,一个访问者修改了所访问的对象,一个没有进行访问。

I have a problem with duplication of identical code for const and non-const versions. I can illustrate the problem with some code. Here are two sample visitors, one which modifies the visited objects and one which does not.

struct VisitorRead 
{
    template <class T>
    void operator()(T &t) { std::cin >> t; }
};

struct VisitorWrite 
{
    template <class T> 
    void operator()(const T &t) { std::cout << t << "\n"; }
};

现在这是一个聚合对象-它只有两个数据成员,但是我的实际代码复杂得多:

Now here is an aggregate object - this has just two data members but my actual code is much more complex:

struct Aggregate
{
    int i;
    double d;

    template <class Visitor>
    void operator()(Visitor &v)
    {
        v(i);
        v(d);
    }
    template <class Visitor>
    void operator()(Visitor &v) const
    {
        v(i);
        v(d);
    }
};

以及用于演示上述内容的函数:

And a function to demonstrate the above:

static void test()
{
    Aggregate a;
    a(VisitorRead());
    const Aggregate b(a);
    b(VisitorWrite());
}

现在,这里的问题是 Aggregate的重复:: operator()用于 const 和非< const 版本。

Now, the problem here is the duplication of Aggregate::operator() for const and non-const versions.

是否可以避免重复执行此代码?

Is it somehow possible to avoid duplication of this code?

我有一个解决方案是这样:

I have one solution which is this:

template <class Visitor, class Struct>
void visit(Visitor &v, Struct &s) 
{
    v(s.i);
    v(s.i);
}

static void test2()
{
    Aggregate a;
    visit(VisitorRead(), a);
    const Aggregate b(a);
    visit(VisitorWrite(), b);
}

这意味着 Aggregate :: operator()是必需的,并且没有重复项。但是我对 visit()是泛型而没有提及 Aggregate 类型的事实感到不满意。

This means neither Aggregate::operator() is needed and there is no duplication. But I am not comfortable with the fact that visit() is generic with no mention of type Aggregate.

有更好的方法吗?

推荐答案

我倾向于简单的解决方案,所以我会选择自由函数方法,可能会添加SFINAE以禁用 Aggregate 以外的类型的功能:

I tend to like simple solutions, so I would go for the free-function approach, possibly adding SFINAE to disable the function for types other than Aggregate:

template <typename Visitor, typename T>
typename std::enable_if< std::is_same<Aggregate,
                                   typename std::remove_const<T>::type 
                                  >::value
                       >::type
visit( Visitor & v, T & s ) {  // T can only be Aggregate or Aggregate const
    v(s.i);
    v(s.d);   
}

其中 enable_if is_same remove_const 实际上很容易实现,如果您没有启用C ++ 0x的编译器(或者您没有可以从boost type_traits借用它们)

Where enable_if, is_same and remove_const are actually simple to implement if you don't have a C++0x enabled compiler (or you can borrow them from boost type_traits)

编辑:在编写SFINAE方法时,我意识到在提供普通模板时存在很多问题OP中没有SFINAE的解决方案,其中包括以下事实:如果您需要提供多个 visitable 类型,则不同的模板会发生冲突(即,它们与其他模板一样好) 。通过提供SFINAE,您实际上仅为满足条件的类型提供了 visit 函数,将奇怪的SFINAE转换为等效项:

EDIT: While writing the SFINAE approach I realized that there are quite a few problems in providing the plain templated (no SFINAE) solution in the OP, which include the fact that if you need to provide more than one visitable types, the different templates would collide (i.e. they would be as good a match as the others). By providing SFINAE you are actually providing the visit function only for the types that fulfill the condition, transforming the weird SFINAE into an equivalent to:

// pseudocode, [] to mark *optional*
template <typename Visitor>
void visit( Visitor & v, Aggregate [const] & s ) {
   v( s.i );
   v( s.d );
}

这篇关于涵盖const和非const方法的C ++模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆