joaocandre
joaocandre

Reputation: 1745

How to implicitly convert class template object when passing as argument to function template?

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?

Upvotes: 1

Views: 139

Answers (2)

Peter Ruderman
Peter Ruderman

Reputation: 12485

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.

Upvotes: 1

Max Langhof
Max Langhof

Reputation: 23691

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.

Upvotes: 1

Related Questions