4

I have following template function which has template template parameter as its argument.

template<typename T, 
         template <typename... ELEM> class CONTAINER = std::vector>
void merge(typename CONTAINER<T>::iterator it )
{
   std::cout << *it << std::endl;
}

And the following code uses this code.

std::vector<int> vector1{1,2,3};
merge<int>(begin(vector1));

It works as expected, but when I use

merge(begin(vector1));

It cannot deduce type of T.

I thought that it could deduce type from std::vector<int>::iterator it; as int.

Why the compiler can't deduce the type?

max66
  • 65,235
  • 10
  • 71
  • 111
user150497
  • 490
  • 4
  • 14
  • suggestion: search for "non-deduced context" – max66 Jun 18 '19 at 11:23
  • This question was asked like 3 days ago (and answered): https://stackoverflow.com/questions/56626007/specialize-a-template-class-using-a-nested-name-specifier-of-another-template-cl/ . – Radosław Cybulski Jun 18 '19 at 11:28
  • He is trying exactly the same thing - trying to deduce type T based by T::iterator type. Which is impossible, both in functions and classes. – Radosław Cybulski Jun 18 '19 at 11:49
  • 1
    Note that you also aren't deducing `CONTAINER`, but using the default. `std::set set1 {1, 2, 3}; merge(begin(set1));` [fails](http://coliru.stacked-crooked.com/a/8c7268a8bb01ed9b) – Caleth Jun 18 '19 at 11:49
  • If you only need to get `int` from `decltype(it)`, then use [`std::iterator_traits<>::value_type`](https://en.cppreference.com/w/cpp/iterator/iterator_traits). E.g. `template ::value_type> void merge(Iterator it)` – Caleth Jun 18 '19 at 11:56
  • @RadosławCybulski ah sorry, now I got it. I does boil down to the same, though imho not enough to flag as duplicate – 463035818_is_not_an_ai Jun 18 '19 at 12:04

1 Answers1

6

I thought that it could deduce type from std::vector<int>::iterator it; as int.

Why the compiler can't deduce the type?

No.

The compiler can't: look for "non-deduced context" for more information.

And isn't reasonable expecting a deduction.

Suppose a class as follows

template <typename T>
struct foo
 { using type = int; };

where the type type is always int; whatever is the T type.

And suppose a function as follows

template <typename T>
void bar (typename foo<T>::type i)
 { }

that receive a int value (typename foo<T>::type is always int).

Which T type should be deduced from the following call ?

bar(0);
Community
  • 1
  • 1
max66
  • 65,235
  • 10
  • 71
  • 111
  • I thought "using type = T" in the foo. So 0 is int so as T is int. Is it impossible for compiler? – user150497 Jun 18 '19 at 11:48
  • @user150497 the point is that there are infinitely many `T`s such that `foo::type` is `int`. The language is defined so that it doesn't have to make a choice between them. – Caleth Jun 18 '19 at 11:51
  • 1
    @user150497 - The problem isn't that is impossible. The problem (IMHO, obviously) is that is unreasonable. In your specific and particular case the internal type permit to deduce the template parameter. Generally speaking isn't possible and add a rule (anyway questionable) to deduce the type in particular cases would force the compiler to make a lot additional works to look all possible combinations and accept the code only when a single template matches. – max66 Jun 18 '19 at 11:53