Search code examples
c++c++17implicit-conversion

Use deductions guides in implicit argument conversion


Consider the following mock of type definitions:

template<typename T> struct Foo {};

template<typename T, size_t offset>
struct FooView {
    FooView(const Foo<T>&) {}
};
template<typename T> FooView(const Foo<T>&) -> FooView<T, 0>;

template<typename T, size_t s>
void yada(FooView<T, s> arg) {}

As one can see, we have a type Foo, here representing a collection of things T and a type FooView which shall represent a view into a Foo, together with some offset s (the nature of the offset is not that important). It also offers a deduction guide, from a Foo to a FooView with offset = 0.

Now, consider how this is is used:

Foo<float> foo;
// yada(foo); // <-- error: no matching function for call to 'yada'
yada(FooView{foo});

I would have thought that the implicit constructor paired with the deduction guide was enough to make the commented call work, but I actually have to type out the conversion. Can I somehow make this implicitly convertible?

I have tried introducing an implicit conversion operator in Foo like this:

operator FooView<T, 0>() { return FooView{*this}; }

but to no avail. The compiler still throws the same error.


Solution

  • Class template argument deduction only applies in certain situations, which all require the actual class template placeholder to be used. arg does not trigger deduction, only cls(arg) does.

    yada(foo) just follows the normal rules of overload resolution, and since foo is not a FooView (template deduction doesn't consider conversions), overload resolution fails.

    yada(FooView(foo)) does class template argument deduction because you asked for it. This is always an explicit, on-demand feature.