#Nested template deduction from argument

12 messages · Page 1 of 1 (latest)

jolly vine
#

Why can't T be deduced in the following?

enum class E
{
    e1,
    e2
};

template<typename T>
struct container
{
    template<E e>
    struct iterator {};

    template<E e = E::e1>
    iterator<e> begin() { return iterator<e>{}; }
};

template<typename T, E e>
void function(typename container<T>::template iterator<e> it)
{
    // ...
}

int main()
{
    container<int> c;
    auto it = c.begin();

    function<int>(it);  // fine, takes T = int and deduces e
    function(it);       // "couldn't deduce template parameter T"
}
cold pollenBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For more information use !howto ask.

jade joltBOT
#
Compiler Output
<source>: In function 'int main()':
<source>:29:13: error: no matching function for call to 'function(container<int>::iterator<E::e1>&)'
   29 |     function(it);       // couldn't deduce template parameter T
      |     ~~~~~~~~^~~~
<source>:18:6: note: candidate: 'template<class T, E e> void function(typename container<T>::iterator<e>)'
   18 | void function(typename container<T>::template iterator<e> it)
      |      ^~~~~~~~
<source>:18:6: note:   template argument deduction/substitution failed:
<source>:29:13: note:   couldn't deduce template parameter 'T'
   29 |     function(it);       // couldn't deduce template parameter T
      |     ~~~~~~~~^~~~
Build failed
hollow dove
#

the non-informative answer is that that's just language rule, you're right in a non-deduced context

the somewhat more informative answer is that it's impossible to handle deduction in that context when you can legally do

template <E e>
struct outer_iterator {};

template <typename T>
struct container<T*>
{
  template <E e>
  using iterator = outer_iterator<e>;

  template <E e = E::e1>
  iterator<e> begin() { return {}; }
};

int main()
{
  container<int*> c1;
  auto it1 = c1.begin();
  container<float*> c2;
  auto it2 = c2.begin();
  
  static_assert(std::is_same_v<decltype(it1), decltype(it2)>);
  //function(it1);  // impossible to deduce T, the two calls provide the exact same type but have distinct Ts
  //function(it2);
}
jolly vine
#

that's wild

#

understandable, thanks sadcatup

#

!solved

cold pollenBOT
#

Thank you and let us know if you have any more questions!

jolly vine
#

!unsolve

#

!solved