【问题标题】:C++ Template meta-magic, template call-site qualification deduction mechanismC++模板元魔术,模板调用点限定推演机制
【发布时间】:2011-07-16 18:54:36
【问题描述】:

我为这个例子的冗长道歉,我是从一个项目中设计出来的。注释的第 1 项和第 2 项在以下代码中很重要。

#include <boost/intrusive/set.hpp>

struct x : public boost::intrusive::set_base_hook<>
{
    int y;
};

struct finder
{
    bool operator()(const int & i, const x & _x) const
    { return i < _x.y;}
    bool operator()(const x & _x, const int & i) const
        { return _x.y < i;}
};

class trampoline
{
public:
    void bounce() const /* item 1 */
    {
        /*item 2*/
        boost::intrusive::set<x>::iterator it = _set.find(1,finder()); 
    }

    boost::intrusive::set<x> _set;
};

int main()
{
    trampoline t;
    t.bounce();
}

我不能将非常量迭代器带到我的成员容器(第 2 项),其中范围内的函数是 const,如果我将迭代器切换到 const_iterator 一切正常,或者如果我将封闭函数设为非 const也可以。现在,从以下错误消息中对问题进行了一个小时的逆向工程,这很有意义:

test.cc: 在成员函数 'void trampoline::bounce() const':test.cc:21: 错误:从 'boost::intrusive::tree_iterator<:intrusive::rbtree_impl boost::intrusive::rbtree_node_traits false>, (boost::intrusive::link_mode_type)1u, boost::intrusive:: default_tag, 3>, std::less, long unsigned int, true> >, true>' 到非标量类型 'boost::intrusive::tree_iterator<:intrusive::rbtree_impl ::setopt boost::intrusive::rbtree_node_traits false>, (boost::intrusive::link_mode_type)1u, boost::intrusive::default_tag, 3>, std::less, long unsigned int, true>>, false>' 请求

最终导致我得到以下模板定义(/include/boost/intrusive/detail/tree_node.hpp +72):

/////////////////////////////////////////////////////////////////////////////
//                                                                         //
//                   Implementation of the tree iterator                   //
//                                                                         //
/////////////////////////////////////////////////////////////////////////////

// tree_iterator provides some basic functions for a 
// node oriented bidirectional iterator:
template<class Container, bool IsConst>

这么说我很快就解决了问题......

该模板是如何从封闭函数的调用点传递IsConst 的?我的大脑已经准备好爆炸(据我所知,这很简单,但我很困惑)。详细的解释以及逐步实现来解释机制会很有帮助。

我有一个类似的问题here,关于 C++ 模板机制的类型推断/别名。参考资料受到赞赏,但需要仔细考虑知识:D。如果你有耐心回答这个问题,你可能想尝试就另一个问题形成一个话语。

【问题讨论】:

    标签: c++ templates boost generic-programming const-correctness


    【解决方案1】:

    boost::intrusive::set 的 find() 成员函数不会简单地具有 const 和非常量重载吗?我的意思是,我会这样做:

    template <typename T /*...*/ >
    class set {
      //... 
      public:
        template <bool isConst>
        class iterator {
          //....
        };
        iterator<true> find(/*..*/) const; //notice the const
        iterator<false> find(/*..*/);      //notice no const
    };
    

    这真的不是元编程魔法,只是老式的 const 正确性。

    【讨论】:

    • 来吧,不可能这么简单的,难怪我的脑子都快炸了。我是老派,一切都是void * 类型的人=D。所以 const 重载是由编译器 =D 从成员对象中提取的,然后它们是通过违反类型别名的人工 const 语义强制(即它们不是可用的有效复制构造函数)。我对“他们在 C++ 中没有返回类型的多态性”的口头禅感到困惑。
    • 如果您将调用函数的对象实例视为函数调用的第一个(隐藏)参数,那么它在重载机制中非常有意义。成员函数的 cv 限定符应该被认为是第一个(隐藏)参数的 cv 限定符。编译器会找到最匹配的重载,因此非常量对象在可用时调用非常量函数,因为它是更好匹配的重载版本。
    【解决方案2】:

    喜欢吗?

    Foo<false> bar();
    Foo<true> bar() const;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      相关资源
      最近更新 更多