c++ - Variadic template argument deduction fails when passing initializer lists -
bar
holds std::vector
of std::pair
s of std::array
s of foovalueadaptor
s. foovalueadaptor
implicitly converts int
bool
foovalue
, makes little sense in contrived example, perfect sense in application. implemented convenience function bar::addentries
adding multiple entries @ once, calling more 2 arguments fails compile using gcc 4.8.0. see error messages below.
#include <array> #include <utility> #include <vector> enum class foovalue { a, b, c }; class foovalueadaptor { public: foovalueadaptor(bool value) : m_value(static_cast<foovalue>(value)) { } foovalueadaptor(int value) : m_value(static_cast<foovalue>(static_cast<bool>(value))) { } foovalueadaptor(foovalue value) : m_value(value) { } operator foovalue() { return m_value; } operator bool() { return m_value == foovalue::c; } private: foovalue m_value; }; template<std::size_t nfirst, std::size_t nsecond> class bar { public: typedef std::array<foovalueadaptor, nfirst> first; typedef std::array<foovalueadaptor, nsecond> second; typedef std::pair<first, second> entry; bar() : m_table() { } void addentry(first first, second second) { m_table.push_back(std::make_pair(first, second)); } template <typename... args> void addentries() { } template <typename... args> void addentries(first first, second second, args... args) { addentry(first, second); addentries(args...); } private: std::vector<entry> m_table; }; int main(int argc, char **argv) { bar<2, 1> b; b.addentry({ 0, 0 }, { 0 }); b.addentries( { 0, 1 }, { 0 }, { 1, 0 }, { 0 }, { 1, 1 }, { 1 } ); return 0; }
compiler error messages:
test.cpp: in function ‘int main(int, char**)’: test.cpp:74:2: error: no matching function call ‘bar<2ul, 1ul>::addentries(<brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>, <brace-enclosed initializer list>)’ ); ^ test.cpp:74:2: note: candidates are: test.cpp:53:7: note: template<class ... args> void bar<nfirst, nsecond>::addentries() [with args = {args ...}; long unsigned int nfirst = 2ul; long unsigned int nsecond = 1ul] void addentries() { ^ test.cpp:53:7: note: template argument deduction/substitution failed: test.cpp:74:2: note: candidate expects 0 arguments, 6 provided ); ^ test.cpp:57:7: note: void bar<nfirst, nsecond>::addentries(bar<nfirst, nsecond>::first, bar<nfirst, nsecond>::second, args ...) [with args = {}; long unsigned int nfirst = 2ul; long unsigned int nsecond = 1ul; bar<nfirst, nsecond>::first = std::array<foovalueadaptor, 2ul>; bar<nfirst, nsecond>::second = std::array<foovalueadaptor, 1ul>] void addentries(first first, second second, args... args) { ^ test.cpp:57:7: note: candidate expects 2 arguments, 6 provided
how can compiler's deduction along?
you need tell compiler explicitly need:
void addentries(std::initializer_list<std::pair<first, second>> il) { for( const auto& e : il ) { addentry(e.first,e.second); } }
and call this:
b.addentry({{ 0, 0 }}, {{ 0 }}); b.addentries({ {{{ 0, 1 }}, {{ 0 }}}, {{{ 1, 0 }}, {{ 0 }}}, {{{ 1, 1 }}, {{ 1 }}} });
notice huge amount of curly brackets, think above correct syntax. fewer brackets accepted both gcc 4.8 , clang 3.2, clang gives lots of warnings, above fixes that. people working on "fix", that'll take time.
Comments
Post a Comment