Ошибка компиляции с (/ permissive-) при создании 'ClassType'из' std :: unique_ptr <Derived>' - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть фрагмент кода, который работал должным образом, когда настройки режима соответствия были отключены. Когда я устанавливаю режим соответствия (/ permissive-). Я сталкиваюсь с ошибкой в ​​части кода, где задействован параметр шаблона шаблона.

Мой код выглядит следующим образом:

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; 
}

В строке 2 отображается ошибка компиляции, когда для режима соответствия установлено значение ON,Это исправляется, если я добавлю другой конструктор, как показано ниже:

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

Однако я хочу включить эту функцию, только если параметр шаблона для D получен из параметра шаблона T или D получен из T,поэтому я изменил условие на:

 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;
    }

Этот код дает ошибку компиляции, потому что здесь D равно std::unique_ptr<Derived>, а T равно std::unique_ptr<Base>. Следовательно, is_convertible терпит неудачу.

Как я могу гарантировать, что этот ctor включен только для унаследованных классов? И почему эта ошибка возникает при включенном режиме соответствия, если это режим соответствия ZC, то какой именно? Я пытался переопределить два этапа, это не сработало?

1 Ответ

1 голос
/ 11 ноября 2019
template <typename D, typename T> 
using IsConvertibleToBase = std::enable_if_t<std::is_convertible_v<D*, T*>>;

С приведенным выше определением, D* и T* будут ошибкой, если IsConvertibleToBase используется с unique_ptr.

Одно из решений - использовать pointer_traits, который будет работать длялюбой тип указателя:

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>>;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...