2015-02-18 2 views
0

НКУ не дает мне ошибку на примере я сделал, когда я надеялся, что это будет:Почему не GCC дает мне ошибку

class CannotBeCopied { 
public: 
    CannotBeCopied(const CannotBeCopied&) = delete; 
    CannotBeCopied& operator=(const CannotBeCopied&) =delete; 
    CannotBeCopied() { } 
    ~CannotBeCopied() { } 
}; 

template<class T> 
class FirstVector { 
public: 
    FirstVector() { 
     size = 1; 
     data = new T[size]; 
    } 

    ~FirstVector() { 
     delete[] data; 
    } 

    FirstVector(const FirstVector& source) { 
     size = source.size; 
     data = new T[size]; 
     for(int k=0;k!=size;k++) { 
      data[k] = source.data[k]; //<--I EXPECT AN ERROR HERE 
     } 
    } 
private: 
    int size; 
    T* data; 
}; 

Эта ошибка не происходит, когда копия конструктор не используется (т. е. он возникает, когда используется конструктор копирования).

Из-за шаблона я не могу просто переместить copy-ctor в файл кода и сбой при его компиляции.

Как я могу получить это, чтобы потерпеть неудачу?

Это не SFINAE, оно не должно быть способным создать экземпляр шаблона. Если копия-т е р сам был метод шаблона (например, поместив:.

template<class U=T> 

на линии выше, то было бы SFINAE

Я использую GCC 4.8.1, -pedantic -Wall -Wextra конечно, и -std=c++11

Я надеялся получить эту неудачу с:

int main() { 
    FirstVector<CannotBeCopied> whatever; 
} 

Я знаю, что GCC просто лениться и не делать работу не нужно, но мне не нравится-е если я должен явно создать экземпляр этого шаблона в файле кода, я бы получил ошибку. Есть ли способ получить ошибку, которую я хочу?

+0

Вы пытались вызвать конструктор копирования 'FirstVector '? – immibis

+0

О да, @immibis - если вы на самом деле используете его, он дает ошибку. Он должен давать ошибку всякий раз, когда создается экземпляр с типом без копирования. –

+0

Спецификация языка Java вызывает указатели Java, указатели. Просто покажите им это. –

ответ

1

Это не просто вопрос GCC, ленивый; утвердительно запрещено делать то, что вы хотите, чтобы он делал по стандарту. [Temp.inst]/p1, 2, 11:

1 Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. [...] The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or exception-specifications of the class member functions [...]

2 Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist. [...]

11 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation.

Это позволяет иметь, например, std::vector х переходе только типов. Их конструкторы копий не будут компилироваться, но до тех пор, пока вы их не используете, std::vector<std::unique_ptr<T>> отлично подходит.

Чтобы заставить его потерпеть неудачу, вы можете использовать static_assert внутри FirstVector:

static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible"); 

Заметим, однако, что это только проверяет, что объявление конструктора копии является доступным и не удаляется, а не о том, что тело конструктора копирования будет компилироваться, что означает, что он будет ложно сообщать, что std::vector<std::unique_ptr<T>> является копией.

+0

Спасибо за! Приятно иметь ответ, который задает вопрос и отвечает на него правильно! Спасибо Вам большое. –

+0

Я бы поднял голову, но не могу. –

3

Если вы фактически не создаете экземпляр своего шаблона, конструктор копирования не нужно вызывать - код шаблона даже не будет создан для CannotBeCopied, если вы его не используете. Вызов конструктора копии, и вы получите сообщение об ошибке:

FirstVector<CannotBeCopied> a; 
FirstVector<CannotBeCopied> b = a; 

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

template class FirstVector<CannotBeCopied>; 

(§14.7.2 спецификации языка)

+0

Первой строкой этого должно быть достаточно, чтобы вызвать ошибку. Если вы EXPERICITLY создаете экземпляр шаблона, вы получите ошибку (как если бы вы положили ее в файл кода) –

+0

Помните 'FirstVector a;' означает 'сделать тип 'FirstVector ', который не может быть выполнен. –

+2

@I 'mGettingThere: Нет, это может быть сделано. Его просто невозможно скопировать. – urzeit

3

Шаблоны в C++ - только материализовались, когда они используются. Все остальное было бы слишком дорого.

Как вы, возможно, слышали, шаблоны C++ завершены, поэтому оценка их может быть безумно дорогой. IIRC был пример где-то из Fibonnaci < 17>, который бы вычислил этот компилятор ...

В частности, это означает, что мертвый код будет устранен, а компилятор C++ будет работать только после попытки использования конструктор копирования.

Смежные вопросы