Stack Exchange
Compilation Error with (/permissive-) while creating a 'ClassType<std::unique_ptr<Base>>' from 'std::unique_ptr<Derived>'
I have a code snippet which used to work properly when conformance mode settings were set to off. When I set the conformance mode to (/permissive-). I am facing error in part of the code where template template parameter is involved.
My code is as follows:
template <typename T> using IsNotLValue = std::enable_if_t<!std::is_lvalue_reference_v<T>>;

// Base Class Template
template <typename T> class MyClassBase 
{ 
   protected:   
       template <typename T_ = T, typename = IsNotLValue<T_>>   
       explicit MyClassBase(T &&ptr) : ptr_(std::move(ptr))
       { 
          std::cout << "MyClassBase ::IsNotLValue" << std::endl; 
       }

       T ptr_ = nullptr; 
};


// Derived Class Template
template<typename T> class MyClass : public MyClassBase<T> 
{ 
  public:

    template <typename T_ = T, typename = IsNotLValue<T_>> 
    MyClass(T &&ptr) : MyClassBase<T>(std::move(ptr))   
    {       
      std::cout << "MyClass :: IsNotLValue" << std::endl;   
    }
};

// Base Class
class Base 
{  
 public:    
   int x = 0;   
   Base() : x(10) {}
};

// Derived Class
class Derived : public Base 
{ 
 public:    
    Derived() :Base(), y(20) {}
    int y = 0; 
};

// Function returning MyClass Object to pointer to Base Class Type
MyClass<Base*> ptrToBase()
{   
  return new Derived();    // Line 1 : OK
}

// Function returning uniqueptr to MyClass Object to pointer to Base Class Type
MyClass<std::unique_ptr<Base>> uniquePtrToBase() 
{   
  return std::make_unique<Derived>(); // Line 2 :compilation error here
}

int main() 
{   
  auto pUB = uniquePtrToBase();     
  auto pB = ptrToBase();
  return 0; 
}

Line 2 is giving compilation error when conformance mode is set to ON.
It is getting fixed, If I add another constructor as below:
template <typename D, typename = IsNotLValue<D>>
        MyClass(D &&ptr) : MyClassBase<T>(std::move(ptr))   
        { 
          std::cout << "MyClass for uniqueptr" << std::endl;    
        }  

However, I want to enable this function only if template parameter for D is derived from template parameter of T or D is derived from T, so I modified the condition to :
 template <typename D, typename T> using IsConvertibleToBase =
     std::enable_if_t<std::is_convertible_v<D*, T*>>;

    template <typename D, typename = IsConvertibleToBase<D, T>>
    MyClass(D &&ptr) : MyClassBase<T>(std::move(ptr))
    {
        std::cout << "MyClass :: IsConvertibleToBase" << std::endl;
    }

This code is giving compilation error because, here D is std::unique_ptr<Derived> and T is std::unique_ptr<Base>. Hence, is_convertible is failing.
How can I ensure that this ctor is enabled only for inherited classes?
And
Why this error is occurring with conformance mode on, if its the ZC conformance mode, then which one? I tried overriding twoPhase, that didnt work?

There are no template template parameters in this code. What you do have is some default template arguments which are class template specializations.

ok.. then my understanding of template template parameter is not correct I suppose.

A template template parameter looks like template <template <typename> class P> ...

template <typename D, typename T> 
using IsConvertibleToBase = std::enable_if_t<std::is_convertible_v<D*, T*>>;

With above definition, D* and T* will be an error when IsConvertibleToBase is used with unique_ptr.
One solution is to use pointer_traits which will work for any pointer-like type:
template <typename D, typename T> 
using IsConvertibleToBase = std::enable_if_t<
    std::is_convertible_v<typename std::pointer_traits<D>::pointer, 
                          typename std::pointer_traits<T>::pointer>>;

