G CC пропускает некоторые ошибки или предупреждения - PullRequest
1 голос
/ 04 августа 2020

Рассмотрим этот конструктор копирования шаблона класса, который имеет ошибку:

MyClass( MyClass const& other )
  : m_x( other.n_x )  // typo: should be `other.m_x`.
{
  // does something
}

Или эту перегрузку оператора присваивания копии, которая ничего не возвращает (return-type предупреждение):

MyClass& operator=( MyClass const& other )
{
   // does something
   // WARNING: with no `return *this`.
}

Несколько раз случалось, что G CC сначала компилирует код без каких-либо ошибок / предупреждений, а позже, после некоторых изменений в других частях кода, он жалуется на проблему, которая уже была там (в основном в конструкторах или Насколько я помню, операторы присваивания).

Игнорирует ли G CC функции шаблона или функции-члены класса шаблона, которые не создаются полностью во всем коде? Что происходит под капотом?

Я использую G CC 9.3 и G CC 10.1 с -O3 -Wall -Wpedantic -Werror.

UPDATE Как предложил @someprogrammerdude, вот минимальный воспроизводимый пример:

template< typename T >
class MyClass {
public:
  MyClass( T x ) : m_x( x ) { };
  MyClass( MyClass const& other )
    : m_x( other.n_x )
  {
    std::cout << "in copy constructor" << std::endl;
  }

  MyClass& operator=( MyClass const& other )
  {
    this->m_x = other.m_x;
  }

  T m_x;
};

и вот пример использования, который компилируется как есть. Но раскомментирование некоторых частей дает ошибку или предупреждение.

int main()
{
  MyClass< int > c( 2 );
  std::cout << c.m_x << std::endl;

  /* Uncommenting these lines gives an error in constructor.
   * error: ‘const class MyClass<int>’ has no member named ‘n_x’*/
  //MyClass< int > d = c;
  //std::cout << d.m_x << std::endl;

  /* Uncommenting these lines gives a warning in copy assignment operator.
   * error: no return statement in function returning non-void [-Werror=return-type] */
  //MyClass< int > d( 3 );
  //d = c;
  //std::cout << d.m_x << std::endl;
  return 0;
}

Теперь, когда я создал этот пример, мне стало понятнее. Итак, не было бы никакой проверки, если бы она не была создана?

Ответы [ 2 ]

3 голосов
/ 04 августа 2020

G CC проверяет шаблоны только с помощью c checker, если они не были созданы. Стандарт не требует даже этого.

Это возможно, если ваш класс шаблона является производным от другого шаблона. Неизвестно, будет ли этот шаблон иметь специализацию с таким членом или нет.

Например, этот код все еще действителен

template <template <class> class T, class V>
struct A {
    V m_x;
};

template <template <class> class T, class V>
struct B : A <T, V>
{
   V t;
    
   V getY() { return this->m_y; } 
  // the `this->` is needed exactly because `m_y` wasn't declared
    
   B(B& a) : t(a.m_y) {}
};

, потому что он может сопровождаться и использоваться только с этой специализацией :

template <class V>
struct A<std::complex, V> {
    V m_x;
    V m_y;
};

В вашем конкретном примере other.n_x отмечает n_x как зависящий от параметров шаблона MyClass (аналогично this-> идиоме), поэтому возможно, что n_x будет существовать позже. Если он не будет существовать в момент замены и создания экземпляра, это приведет к ошибке компиляции, но не раньше.

1 голос
/ 04 августа 2020

Члены шаблона класса создаются по запросу отдельно от самого класса. Так работает язык. Код шаблона компилируется при его создании; до тех пор источник - это просто анализируемый , который не проверяет семантику, а только некоторый базовый синтаксис структуры c (например, соответствующие скобки, круглые скобки и т. д. c).

MyClass конструктор копирования будет создан при первом копировании объекта этого типа или никогда, если он никогда не копируется.

Вы можете попросить компилятор создать экземпляры всех элементов шаблона для определенного типа, используя явное создание экземпляра синтаксис:

template class MyClass<int>;  // explicit instantiation

Примечание: оптимизирующий компоновщик (например, g ++) удалит неиспользуемый код, поэтому это не приведет к увеличению двоичного размера, только немного увеличится время компиляции.

...