c++ - ambiguous operator[] in variadic template -


i'm trying compile example, variadic class template inherits variadic amount of bases, each of implements different operator[]:

#include <iostream>  template <typename t> struct field {   typename t::value_type storage;    typename t::value_type &operator[](const t &c) {     return storage;   } };  template<typename... fields> struct ctmap : public field<fields>... { };  int main() {     struct age { typedef int value_type; };     struct last_name { typedef std::string value_type; };      ctmap<last_name, age> person;      person[last_name()] = "smith";     person[age()] = 104;     std::cout << "hello world!" << std::endl;     return 0; } 

when compile gcc (debian 4.9.2-10), following error

main.cpp: in function ‘int main()’: main.cpp:22:23: error: request member ‘operator[]’ ambiguous      person[last_name()] = "smith";                        ^ main.cpp:7:27: note: candidates are: typename t::value_type& field<t>::operator[](const t&) [with t = main()::age; typename t::value_type = int]    typename t::value_type &operator[](const t &c) {                            ^ main.cpp:7:27: note:                 typename t::value_type& field<t>::operator[](const t&) [with t = main()::last_name; typename t::value_type = std::basic_string<char>] main.cpp:23:17: error: request member ‘operator[]’ ambiguous      person[age()] = 104;                  ^ main.cpp:7:27: note: candidates are: typename t::value_type& field<t>::operator[](const t&) [with t = main()::age; typename t::value_type = int]    typename t::value_type &operator[](const t &c) {                            ^ main.cpp:7:27: note:                 typename t::value_type& field<t>::operator[](const t&) [with t = main()::last_name; typename t::value_type = std::basic_string<char>] 

why ambiguous?

a portable way do want roughly:

template<class...ts> struct operator_index_inherit {}; template<class t0, class t1, class...ts> struct operator_index_inherit<t0, t1, ts...>:   t0, operator_index_inherit<t1, ts...> {   using t0::operator[];   using operator_index_inherit<t1, ts...>::operator[]; }; template<class t0> struct operator_index_inherit<t0>:   t0 {   using t0::operator[]; }; 

then:

template<class... fields> struct ctmap : operator_index_inherit<field<fields>...> {   using base = operator_index_inherit<field<fields>...>;   using base::operator[]; }; 

here linearly inherit each of types, , using operator[] on our parents.

if using field<fields>::operator[]...; not have this.

some care has taken constructors (which did not take), might not need this.

live example.


what going wrong depends on details of standard less of. basically, mixing operators , inheritance , overloading in complex way. if code standard compliant (which may or may not be), compliant in way compilers die on.


Comments