2014-10-20 54 views
5

我有一個模板類,Iterable;爲此我想超載begin()end()免費功能。它將數據存儲爲的unique_ptr,但爲方便起見,界面使用boost::indirect_iterator模板上的begin()和end()自由函數超載

我的代碼在CLang-3.5下生成並運行,但我嘗試了g++-4.9,但它沒有。但我不知道爲什麼? (哪個編譯器有正確的行爲)。

template<typename T> 
using SimpleVec = std::vector<T, std::allocator<T>>; 

template <typename T, 
      template <typename> class Container = SimpleVec, 
      class String = std::string> 
class Iterable 
{ 
     template <typename friendT, 
        template <typename> class friendContainer, 
        class friendString> 
     friend boost::indirect_iterator<typename friendContainer<std::unique_ptr<friendT>>::iterator> 
      begin(Iterable<friendT, friendContainer, friendString>& i); 

     template <typename friendT, 
        template <typename> class friendContainer, 
        class friendString> 
     friend boost::indirect_iterator<typename friendContainer<std::unique_ptr<friendT>>::iterator> 
      end(Iterable<friendT, friendContainer, friendString>& i); 
}; 

和自由的功能:

template <typename T, 
      template <typename> class Container = SimpleVec, 
      class String = std::string> 
boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator> 
    begin(Iterable<T, Container, String>& i) 
{ 
    return boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator>(begin(i._c)); 
} 

template <typename T, 
      template <typename> class Container = SimpleVec, 
      class String = std::string> 
boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator> 
    end(Iterable<T, Container, String>& i) 
{ 
    return boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator>(end(i._c)); 
} 

g++,錯誤的是:

../../API/net/session/ClientSession.h:83:29: error: call of overloaded 'begin(GroupManager&)' is ambiguous 
     for(auto& grp : groups()) 
          ^
../../API/net/session/ClientSession.h:83:29: note: candidates are: 
In file included from ../../API/net/session/../permission/full/PermissionManager.h:5:0, 
       from ../../API/net/session/Session.h:3, 
       from ../../API/net/session/ClientSession.h:2, 
       from ../../API/net/session/ClientSessionBuilder.h:2, 
       from ../client/main.cpp:2: 
../../API/net/session/../permission/full/../../Iterable.h:22:4: note: boost::indirect_iterator<typename friendContainer<std::unique_ptr<friendT> >::iterator> begin(Iterable<friendT, friendContainer, friendString>&) [with friendT = Group; friendContainer = SimpleVec; friendString = std::basic_string<char>; T = Permission; Container = SimpleVec; String = std::basic_string<char>; typename friendContainer<std::unique_ptr<friendT> >::iterator = __gnu_cxx::__normal_iterator<std::unique_ptr<Group, std::default_delete<Group> >*, std::vector<std::unique_ptr<Group, std::default_delete<Group> >, std::allocator<std::unique_ptr<Group, std::default_delete<Group> > > > >] 
    begin(Iterable<friendT, friendContainer, friendString>& i); 
    ^
../../API/net/session/../permission/full/../../Iterable.h:142:2: note: boost::indirect_iterator<typename Container<std::unique_ptr<_Tp> >::iterator> begin(Iterable<T, Container, String>&) [with T = Group; Container = SimpleVec; String = std::basic_string<char>; typename Container<std::unique_ptr<_Tp> >::iterator = __gnu_cxx::__normal_iterator<std::unique_ptr<Group, std::default_delete<Group> >*, std::vector<std::unique_ptr<Group, std::default_delete<Group> >, std::allocator<std::unique_ptr<Group, std::default_delete<Group> > > > >] 
    begin(Iterable<T, Container, String>& i) 
^

所以它看起來像g++看到friend聲明爲其他功能?

回答

4

我終於找到答案(這是更可讀)感謝@ sehe的回答和this cppreference page

template <typename T, 
      template <typename> class Container = SimpleVec, 
      class String = std::string> 
class Iterable 
{ 
     friend boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator> 
      begin(Iterable& i) 
     { 
      return boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator>(begin(i._c)); 
     } 

     friend boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator> 
      end(Iterable& i) 
     { 
      return boost::indirect_iterator<typename Container<std::unique_ptr<T>>::iterator>(end(i._c)); 
     } 
}; 
3

一個友元函數作爲一個在包含範圍中聲明的自由函數。

它將朋友聲明視爲另一個函數,因爲它是(事實上,另一個函數模板生成無界函數,所有函數都與自由函數不同)。

有模板一直是相同的,你會得到一個不同的診斷:

main.cpp:13:13: error: redefinition of 'begin' 
char const* begin(X const&) { return data; } 
      ^
main.cpp:9:24: note: previous definition is here 
    friend char const* begin(X const&) { return data; } 
        ^

看到它Live On Coliru

+0

@Yakk oops。固定。該消息現在也更具描述性。雖然,OP的問題可能更多的是模板函數,而不是自由函數的類內定義。我的+1與其他答案 – sehe 2014-10-20 19:12:37

+0

接下來的問題是,OP的兩個版本如何不相同?而OP的「朋友」沒有身體,你的確如此。 – Yakk 2014-10-20 19:51:57

+0

@Yakk。嘆。 [我搞砸了](http://coliru.stacked-crooked.com/a/606a4d268719ca09),沒有我:| |你是對的。除了提示內聯定義之外,我沒有解釋任何這個謎團。將在早上刪除。乾杯 – sehe 2014-10-20 21:24:19