#5419 closed Patches (wontfix)
assign fails with C++0x compilers
| Reported by: | Chris Jefferson | Owned by: | James E. King, III |
|---|---|---|---|
| Milestone: | Boost 1.69 | Component: | assign |
| Version: | Boost 1.47.0 | Severity: | Problem |
| Keywords: | Cc: |
Description
Assign is failing to compile with a clang and libc++ when in C++0x mode. I believe this is because C++0x has two operator= for each container, for example vector has:
operator=(const std::vector<T>&) operator=(initialiser_list<T>)
And the technique of using (from list_of.hpp)
template< class Container >
operator Container() const {
return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();
}
Can't choose between these two options.
I don't know the best, or really any good way, to fix this unfortunately.
Attachments (3)
Change History (15)
comment:1 by , 12 years ago
comment:2 by , 11 years ago
Attached a patch for this ticket.
I use C++0x's "default template arguments for function templates" feature
to SFINAE out the conversion operator to initializer_list.
(While Container is required to have difference_type nested-type,
initializer_list does not have it.
by , 11 years ago
| Attachment: | list_of_cxx0x_2.patch added |
|---|
A new patch for list_of.hpp (previous patch is incomplete).
comment:3 by , 11 years ago
A new patch attached.
The previous patch only fixes generic_list,
but this patch fixes both generic_list and static_generic_list.
by , 11 years ago
| Attachment: | assign_cxx0x.patch added |
|---|
A patch for boost/assign/list_of.hpp and libs/assign/test/. This patch includes the previous fixes.
comment:4 by , 11 years ago
A patch attached. I believe it's the final patch for this problem ;)
With this patch, the test (libs/assign/test) runs successfully on
- gcc-4.3.6, gcc-4.4.6, gcc-4.5.3, gcc-4.6.1
- clang (trunk)
The test runs in both C++03 and C++0x modes.
The previous patch fixes the problem of ambiguity with std::initializer_list<T>.
However, in order to pass all the test, this is not enough.
I added the following fixes:
- (
boost/assign/list_of.hpp) The ambiguity problem is also happened withstd::allocator<T>. Adding dummy template parameter to the conversion function can avoid this ambiguity:template < class Container , class Dummy1 = typename Container::difference_type , class Dummy2 = typename Container::iterator > operator Container() const { // ... }std::initializer_list<T>is SFINAE'ed out byDummy1andstd::allocator<T>is SFINAE'ed out byDummy2.
- (
libs/assign/test/std.cpp) In C++0x mode of some compilers, the codeusing namespace std; // ... typedef pair<string,int> tuple;
interact badly withstd::tuple<Args…>and causes compiler errors. Simply changing thetypedeffixes the problem:using namespace std; // ... typedef pair<string,int> two;
- (
libs/assign/test/list_inserter.cpp) In C++0x mode of gcc-4.3,std::vector<T>does not havevoid push_back(const T&);
but it hastemplate <typename Args...> void push_back(Args&&...);
So the codepush_back_t push_back_func = &vector<int>::push_back;
should be changed topush_back_t push_back_func = &vector<int>::push_back<const int&>;
comment:5 by , 11 years ago
The rationale for using SFINAE by "default template arguments for function templates" rather than restricting the number of template parameters by variadic templates is that
- User-defined containers can have only one template parameter. In this case, the variadic template approach breaks the existing code.
- Variadic templates cannot handle ordinary (type) template parameters and non-type template parameters simultaneously. This means that we have to define different overloads for different patterns of non-type template parameters. It's a mess.
comment:6 by , 11 years ago
| Type: | Bugs → Patches |
|---|
comment:7 by , 9 years ago
Why was the type of this ticket changed to Patches? For me it's kind of a bug. The problem appears when trying to compile a code that uses Boost.Assign, in C++11 mode (in my case the problem is with assignment boost::assign::map_list_of() to boost::unordered_map).
What are the chances to push this forward? Is there any workaround? I may provide a test case if it helps.
comment:8 by , 4 years ago
| Owner: | changed from to |
|---|
comment:10 by , 4 years ago
| Milestone: | To Be Determined → Boost 1.69 |
|---|
comment:11 by , 4 years ago
So it looks like I cannot reopen this, but it was reported in #7364 so I will submit a PR

Hm. That could be problematic.
Since initializer lists only take on template argument, we should be able to do the following:
replace
template< class Container > operator Container() const
with
template< template<class,class> Container, class T, class A > operator Container<T,A>() const
Furthermore, this only takes care of templates with two arguments like standard sequence. Therefore, we also need to add overloads with 3 and four arguments.
A bigger problem arises with something like boost::multi_index_container which may have many template arguments ... hm ... maybe the C++11 solution is to use variadic templates to cover all cases with more than one template argument.
If you can make a patch and test it, I'd be happy to apply it.
regards
-Thorsten