#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 byDummy1
andstd::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 thetypedef
fixes 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