1

Considering the following small code snippet:

template <typename T>
class A{
public:
    A() { };
    ~A() { };
    // ...
    template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }    
};

template <typename T = float>
void myFunc(const std::vector<T>& _arg){
    printf("myFunc\n");
}

int main(int argc, char const *argv[]) { 
    A<int> foo;
    myFunc(foo);
}

When trying to compile, I get the error

template argument deduction/substitution failed: [...]  ‘A<int>’ is not derived from ‘const std::vector<T>’

While, on the other hand, if myFunc is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc accepts multiple vector types as argument, the compiler does not know to what type it should convert foo to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A to myFunc?

YSC
  • 38,212
  • 9
  • 96
  • 149
joaocandre
  • 1,621
  • 4
  • 25
  • 42
  • 2
    No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not. – NathanOliver Nov 21 '18 at 17:30
  • 3
    please provide the code that causes the error (see also [mcve]). Its not clear how `myFunc` and `A` are related. – 463035818_is_not_an_ai Nov 21 '18 at 17:31
  • @NathanOliver If `myFunc` is untemplated and takes, for instance, an `std::vector` as argument, `foo` is cast implicitely. Shouldn't the default value for `myFunc` template (`float`) be used then? – joaocandre Nov 21 '18 at 17:37
  • @user463035818 I've added a small `main()` to reproduce the error. `A` and `myFunc` aren't related. – joaocandre Nov 21 '18 at 17:38
  • The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as `operator std::vector()` and you will still get the same error. You can make the entire class `A` non-template either andbut makes no difference, still the same error. – n. m. could be an AI Nov 21 '18 at 18:09

2 Answers2

1

Implicit conversions are not considered when attempting to deduce template parameters. Since A<int> cannot match const std::vector<T>, the myFunc template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).

For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
1

The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo) the compiler is unable to determine a type for T. And that's really the end of the story.

See Template argument deduction on C++ reference.

Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.

See "C++ Function Templates: How Do They Really Work?" on youtube.

Peter Ruderman
  • 12,241
  • 1
  • 36
  • 58