2011-03-16 73 views
2

我爲這個例子的冗長表示歉意,我從一個項目中設計出它。在下面的代碼中,評論項目1和項目2是重要的。C++模板元魔法,模板調用網站資格演繹機制

#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(); 
} 

我不能把一個非const itereator到我的會員容器(第2項),其中範圍的功能是常量,如果切換迭代器的常量性,一切工作正常,或者如果我做它的函數非const也可以。非常有意義,現在,逆向工程的一個小時從以下錯誤消息的問題後:

test.cc: In member function ‘void trampoline::bounce() const’:test.cc:21: error: conversion from ‘boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<x, boost::intrusive::rbtree_node_traits<void*, false>, (boost::intrusive::link_mode_type)1u, boost::intrusive::default_tag, 3>, std::less<x>, long unsigned int, true> >, true>’ to non-scalar type ‘boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<x, boost::intrusive::rbtree_node_traits<void*, false>, (boost::intrusive::link_mode_type)1u, boost::intrusive::default_tag, 3>, std::less<x>, long unsigned int, true> >, false>’ requested

最終導致我下面的模板定義(/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。如果你有耐心回答這個問題,你可能想嘗試就另一個問題形成一個話語。

回答

1

boost::intrusive::set的find()成員函數是不是隻有const和non-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正確性。

+0

來吧,它不能這麼簡單,難怪我的大腦已經準備好爆炸了。我是個老派,一切都是'空虛'型的人= D。因此,const重載是由編譯器= D從成員對象中獲取的,然後它們是通過違反類型別名(--i.e。,它們不是有效的可用副本構造函數)而實施的人工常量語義。我被「他們在C++中沒有返回類型的多態派」的念頭弄糊塗了。 – 2011-03-16 19:24:11

+0

如果您認爲函數被調用的對象實例作爲函數調用的第一個(隱藏)參數,那麼它在重載機制中很有意義。成員函數的cv限定符應該被認爲是這個第一個(隱藏)參數的cv限定符。編譯器找到最匹配的重載,所以非const對象在可用時調用非const函數,因爲它是更好的匹配重載版本。 – 2011-03-16 20:20:37

1

那樣?

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