Begin () and end () free template overload function

I have a template, Iterable ; for which I want to overload the free functions begin() and end() . It saves the data as vector unique_ptr , but for convenience, the interface uses boost::indirect_iterator .

My code builds and works under CLang-3.5 , but I tried on g++-4.9 , and it is not. But I do not know why? (And which compiler has the correct behavior).

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

And free functions:

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

In g++ error is:

 ../../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) ^ 

So, does g++ seem to see friend declaration as another function?

+5
source share
2 answers

I finally managed to find an answer (which is much more readable) thanks to @sehe answer and 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)); } }; 
+4
source

A class function in a class acts as a free function declared in the content area.

He sees the friend’s declaration as another function, because it is (in fact, a different function template that generates unlimited functions, all different from a free function).

If the templates were identical, you would get a different diagnostic:

 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; } ^ 

Watch Live On Coliru

+3
source

Source: https://habr.com/ru/post/1205080/


All Articles