Templated template parameter U<T> does not recognize const qualifier

Viewed 55

I was looking into the following piece of code (no real application, just out of curiosity):

#include <memory>

template <typename T>
struct MyClass{};

template <template <class> class U, class T>
void foo(std::shared_ptr<U<T>> t){ }

template <class U>
void bar(std::shared_ptr<U> t){ }

int main()
{        
    std::shared_ptr<const MyClass<int>> ptr_to_const;
    std::shared_ptr<MyClass<int>> ptr;

    foo(ptr_to_const); // error
    foo(ptr); // OK

    bar(ptr_to_const); // OK
    bar(ptr); // OK
}

However, the compiler fails with

<source>: In function 'int main()':
<source>:17:9: error: could not convert 'ptr_to_const' from 'shared_ptr<MyClass<[...]>>' to 'shared_ptr<MyClass<[...]>>'
   17 |     foo(ptr_to_const); // error
      |         ^~~~~~~~~~~~
      |         |
      |         shared_ptr<MyClass<[...]>>

Lived demo here. It seems that the const qualifier is ignored when using a template template parameter as in foo. Can someone explain me why this won't compile? As expected, calling bar does not cause any problems.

1 Answers

It's a failure of template deduction.

There's no combination of U and T to match std::shared_ptr<U<T>> from std::shared_ptr<const MyClass<int>>. const MyClass isn't a template.

You can overload foo

template <template <class> class U, class T>
void foo(std::shared_ptr<const U<T>> t){ }

template <template <class> class U, class T>
void foo(std::shared_ptr<volatile U<T>> t){ }

template <template <class> class U, class T>
void foo(std::shared_ptr<const volatile U<T>> t){ }
Related