c++ - Cannot explain ambiguous template specializations -


given

template <typename...> struct pack; using t1 = std::tuple<int, char, double>; using t2 = std::tuple<bool, double, int, char>; 

tupletree<pack, t1, t2> shall be

pack<     pack<int, bool>, pack<int, double>, pack<int, int>, pack<int, char>,     pack<char, bool>, pack<char, double>, pack<char, int>, pack<char, char>,     pack<double, bool>, pack<double, double>, pack<double, int>, pack<double, char> > 

and extends number of tuples. easy enough understand definition? ok, have program working correctly:

http://ideone.com/oumezk

but want extend definition to

`tupletreewithrepeats<p, std::index_sequence<is...>, tuples...>` 

where is... indicate number of times each tuple being used repeatedly until moving on next tuple. note <is...> = <1,1,...,1> reduce same tupletree<p, tuples...>. ambiguity i'm stuck these 2 specializations:

tupletreewithrepeatshelper<p, std::index_sequence<is...>, loopnumber, p<ts...>, first, rest...> tupletreewithrepeatshelper<p, std::index_sequence<i, is...>, i, p<ts...>, first, rest...> 

for reason, presence of p<ts...> causes ambiguity because when replace single-named type ambiguity removed. when replace std::index_sequence<is...> std::index_sequence<i, is...>, ambiguity still there. what's going on? , how fix this? here code, same tupletree:

#include <iostream> #include <tuple> #include <type_traits>  template <typename t> struct identity { using type = t; };  // merging packs of types. template <typename...> struct mergepacks;  template <typename pack> struct mergepacks<pack> : identity<pack> {};  template <template <typename...> class p, typename... types1, typename... types2, typename... packs> struct mergepacks<p<types1...>, p<types2...>, packs...> : mergepacks<p<types1..., types2...>, packs...> {};  // appending type pack. template <typename pack, typename t> struct appendtype;  template <template <typename...> class p, typename... ts, typename t> struct appendtype <p<ts...>, t> {     using type = p<ts..., t>; };  // expandpackwithtuple takes pack, , creates n packs each end tuple's elements, n size of tuple. template <template <typename...> class p, typename pack, typename tuple, typename indices> struct expandpackwithtuplehelper;  template <template <typename...> class p, typename pack, typename tuple, std::size_t... is> struct expandpackwithtuplehelper<p, pack, tuple, std::index_sequence<is...>> {     using type = p<typename appendtype<pack, typename std::tuple_element<is, tuple>::type>::type...>; };  template <template <typename...> class p, typename pack, typename tuple> using expandpackwithtuple = typename expandpackwithtuplehelper<p, pack, tuple, std::make_index_sequence<std::tuple_size<tuple>::value>>::type;  // tupletreewithrepeats. template <template <typename...> class p, typename numrepeats, std::size_t loopnumber, typename outputpack, typename... tuples> struct tupletreewithrepeatshelper;  template <template <typename...> class p, std::size_t i, std::size_t... is, std::size_t loopnumber, typename... ts, typename first, typename... rest> struct tupletreewithrepeatshelper<p, std::index_sequence<i, is...>, loopnumber, p<ts...>, first, rest...> :     tupletreewithrepeatshelper<p, std::index_sequence<i, is...>, loopnumber + 1, typename mergepacks<expandpackwithtuple<p, ts, first>...>::type, first, rest...> {};  template <template <typename...> class p, std::size_t i, std::size_t... is, typename... ts, typename first, typename... rest> struct tupletreewithrepeatshelper<p, std::index_sequence<i, is...>, i, p<ts...>, first, rest...> :     tupletreewithrepeatshelper<p, std::index_sequence<is...>, 0, typename mergepacks<expandpackwithtuple<p, ts, first>...>::type, rest...> {};  template <template <typename...> class p, std::size_t... is, std::size_t loopnumber, typename outputpack> struct tupletreewithrepeatshelper<p, std::index_sequence<is...>, loopnumber, outputpack> {     using type = outputpack; };  template <template <typename...> class p, typename numrepeats, typename... tuples> struct tupletreewithrepeats;  template <template <typename...> class p, std::size_t i, std::size_t... is, typename... tuples> struct tupletreewithrepeats<p, std::index_sequence<i, is...>, tuples...> : tupletreewithrepeatshelper<p, std::index_sequence<is...>, 0, p<p<>>, tuples...> {};  // testing template <typename...> struct pack; using t1 = std::tuple<int, char, double>; using t2 = std::tuple<bool, double, int, char>; using t3 = std::tuple<double, int>;  int main() {     std::cout << std::is_same<         tupletreewithrepeats<pack, std::index_sequence<1,1,1>, t1, t2, t3>::type,         pack<             pack<int, bool, double>, pack<int, bool, int>, pack<int, double, double>, pack<int, double, int>, pack<int, int, double>, pack<int, int, int>, pack<int, char, double>, pack<int, char, int>,             pack<char, bool, double>, pack<char, bool, int>, pack<char, double, double>, pack<char, double, int>, pack<char, int, double>, pack<char, int, int>, pack<char, char, double>, pack<char, char, int>,             pack<double, bool, double>, pack<double, bool, int>, pack<double, double, double>, pack<double, double, int>, pack<double, int, double>, pack<double, int, int>, pack<double, char, double>, pack<double, char, int>         >     >::value << '\n';  // ambiguous } 

as far can tell, these 2 should not ambiguous.

regardless, easy workaround implement "with repeats" in terms of "without repeats":

// tupletreewithrepeats. template <template <typename...> class p, typename tuples> struct tupletreewithrepeatshelper;  template <template <typename...> class p, typename... tuples> struct tupletreewithrepeatshelper<p, pack<tuples...>> :     identity<tupletree<p, tuples...>> {};  template <template <typename...> class p, typename numrepeats, typename... tuples>  struct tupletreewithrepeats;  template <template <typename...> class p, std::size_t... is, typename... tuples> struct tupletreewithrepeats<p, std::index_sequence<is...>, tuples...> :     tupletreewithrepeatshelper<p, typename mergepacks<repeat<tuples, is>...>::type> {}; 

where repeat is

template<class t, std::size_t> using id = t;  template<class t, std::size_t... is> pack<id<t, is>...> do_repeat(std::index_sequence<is...>);  template<class t, std::size_t i> using repeat = decltype(do_repeat<t>(std::make_index_sequence<i>())); 

demo. 1 might argue better design.


minimized to:

template<class> class purr { };  template <template <class> class, class> struct meow;  template <template <class> class p> struct meow<p, p<int>> { };  template <template <class> class p, class t> struct meow<p, p<t>> { };  meow<purr, purr<int>> c; 

gcc reports ambiguity, looks bug me. clang handles correctly.


Comments

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -