Reputation: 363
I'm trying to create a static vector-of-vectors and I'm finding that the following code compiles and runs under gcc-4.1.2 but under gcc-4.5.1 it fails to compile with the message
assign.cxx:19:48: error: no matching function for call to ‘to(boost::assign_detail::generic_list<std::basic_string<char> >&)’
Can anyone explain why this happens? If you have any other suggestions about how to do what I'm trying to do then I'd be happy with that instead :).
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>
template <template <typename> class containerType, typename elemType>
containerType<elemType> to( boost::assign_detail::generic_list<elemType> list ) {
containerType<elemType> tempContainer = list;
return tempContainer;
}
static const std::vector<std::vector<std::string> > names = boost::assign::list_of
(to<std::vector>(boost::assign::list_of<std::string>("A")("B")("C") ))
(to<std::vector>(boost::assign::list_of<std::string>("D")("E")("F") ));
int main() {
for( std::vector< std::vector<std::string> >::const_iterator itVec = names.begin(); itVec != names.end(); ++itVec ) {
for( std::vector<std::string>::const_iterator itStr = itVec->begin(); itStr != itVec->end(); ++itStr ) {
std::cout << "Value is " << *itStr << std::endl;
}
}
return 0;
}
Upvotes: 1
Views: 798
Reputation: 63005
The problem stems from the fact that in your definition of to<>()
, containerType
is declared to have only one template parameter, when in fact std::vector<>
has two template parameters.
The fact that this compiles in GCC 4.1.2 only indicates a bug in GCC 4.1.2 -- the code is still inherently incorrect.
Unfortunately, I can't think of a good workaround offhand. The following compiles but restricts you to containers with only two template arguments (wherein the second is the allocator), which may not be what you ultimately want:
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>
template<
template<typename, typename> class containerType,
typename allocatorType,
typename elemType
>
containerType<elemType, allocatorType >
to(boost::assign_detail::generic_list<elemType> const& list)
{
return list; // no need to explicitly construct a containerType instance
}
template<template<typename, typename> class containerType, typename elemType>
containerType<elemType, std::allocator<elemType> >
to(boost::assign_detail::generic_list<elemType> const& list)
{
return to<containerType, std::allocator<elemType> >(list);
}
static std::vector<std::vector<std::string> > names = boost::assign::list_of
(to<std::vector>(boost::assign::list_of<std::string>("A")("B")("C")))
(to<std::vector>(boost::assign::list_of<std::string>("D")("E")("F")));
int main()
{
typedef std::vector<std::vector<std::string> >::const_iterator outer_iter_t;
typedef std::vector<std::string>::const_iterator inner_iter_t;
for (outer_iter_t itVec = names.begin(); itVec != names.end(); ++itVec)
for (inner_iter_t itStr = itVec->begin(); itStr != itVec->end(); ++itStr)
std::cout << "Value is " << *itStr << '\n';
}
EDIT (in response to dribeas' comment): Updated to allow the caller to override the default allocator.
Upvotes: 3
Reputation: 208466
After going around the problem a couple of things, I believe that the simplest solution is not using a template template argument, but rather a type template argument:
template <typename containerType, typename elemType>
containerType to( boost::assign_detail::generic_list<elemType> list ) {
containerType tempContainer = list;
return tempContainer;
}
static const std::vector<std::vector<std::string> > names = boost::assign::list_of
(to<std::vector<std::string> >(boost::assign::list_of<std::string>("A")("B")("C") ))
(to<std::vector<std::string> >(boost::assign::list_of<std::string>("D")("E")("F") ));
It might require a bit more typing in the calling side, but it will take care of the extra template arguments that you are not declaring in your template template argument.
Upvotes: 1
Reputation: 2786
Your call to the function to<std::vector>( ... )
only contains one template parameter, whereas you function declaration contains two. I would try: to<std::vector, std::string>( ... )
Upvotes: -1