Why isn't GCC giving me an error - c++

GCC isn't giving me an error on an example I've made where I was hoping it would:
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;
};
This error doesn't happen when the copy constructor isn't use (that is, it does happen when the copy constructor is used).
Because of the template I cannot simply move the copy-ctor into a code file and have that fail when it compiles.
How can I get this to fail?
This is not SFINAE, it should not be able to instantiate the template. If the copy-ctor was itself a template method (say by putting:
template<class U=T>
on the line above, then it'd be SFINAE.
I am using GCC 4.8.1, -pedantic -Wall -Wextra of course, and -std=c++11
I was hoping to get this to fail with:
int main() {
FirstVector<CannotBeCopied> whatever;
}
I know that GCC is just being lazy and not doing work it doesn't need to, but I do not like that if I were to explicitly instantiate this template in a code file, I'd get an error. Is there a way to get the error I want?

If you don't actually create an instance of your template, the copy constructor doesn't need to be called - the template code will not even be created for CannotBeCopied, if you don't use it. Invoke the copy constructor and you will get the error:
FirstVector<CannotBeCopied> a;
FirstVector<CannotBeCopied> b = a;
Edit: You may also use explicit instantiation of the template with all it's members by adding
template class FirstVector<CannotBeCopied>;
(§14.7.2 of language specification)

Templates in C++ are only materialized when they are used.
Everything else would be too expensive.
As you may have heard, C++ templates are turing complete, so evaluating them can be is insanely expensive. IIRC there was an example somewhere of Fibonnaci<17>, which would have the compiler compute this number...
In particular this means the dead code will be eliminated, and the c++ compiler will only fail once you try to use the copy constructor.

It's not just a matter of GCC being lazy; it is affirmatively prohibited from doing what you want it to do by the standard. [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.
This allows you to have, e.g., std::vectors of move-only types. Their copy constructors will not compile, but as long as you don't use them, a std::vector<std::unique_ptr<T>> is perfectly valid.
To force it to fail, you might use a static_assert inside FirstVector:
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
Note, however, that this only checks that a declaration of the copy constructor is accessible and not deleted, not that the body of the copy constructor will compile, which means that it will falsely report that std::vector<std::unique_ptr<T>> is copy constructible.

Related

Forcing instantiation of all of a template classes member functions

During initial development of a template class, before I've written full test cases, I am finding that I would like the ability to force the compiler to generate the code for every member (including non-static ones) of a template class for a specific set of template parameters, just to make sure all the code at least compiles.
Specifically, I'm using GCC 9 (I don't really need this ability for other compilers, since it's just something I want to temporarily make happen during development); and its c++14, c++17, c++2a and c++20 standards.
For example, I might write the following code:
template <typename D> struct test_me {
D value;
void mistake1 () { value[0] = 0; }
void mistake2 () { mistake1(value); }
// and a bajillion other member functions...
};
And, given that I know in advance the finite set of possible template parameters (let's say int and float here), I just want to make sure they at least compile while I'm working.
Now I can do this, which obviously falls short:
int main () {
test_me<int> i;
test_me<float> f;
}
Since mistake1 and mistake2 aren't generated, the code compiles fine despite the indexed access attempt to a non-array type, and the incorrect function call.
So what I've been doing during development is just writing code that calls all the member functions:
template <typename D> static void testCalls () {
test_me<D> t;
t.mistake1();
t.mistake2();
// and so on... so many mistakes...
}
int main () {
testCalls<int>();
testCalls<float>();
}
But this gets to be a pain, especially when the member functions start to have complex side effects or preconditions, or require nontrivial parameters, or have non-public members and not-yet-developed friends. So, I'd like a way to test compilation without having to explicitly call everything (and, ideally, I'd like to be able to test compilation without modifying any "test" code at all as I add new members).
So my question is: With at least GCC 9, is there a way to force (potentially temporarily) the compiler to generate code for a template class's entire set of members, given template parameters?
Just explicitly instantiate the class:
template struct test_me<int>;
template struct test_me<float>;
Demo
What you are trying to do is not allowed by the language, at least with implicit instantiations of your test class. When you implicitly instantiate test_me with some type, the definitions of the member functions are not allowed to be implicitly instantiated, as per temp.inst#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 static data member of a templated class, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
So if you want to implicitly instantiate all the mistake member functions, you have no choice but to require their instantiation somehow. As in your example with testCalls, you can make calls to those member functions, or you can ODR-use them some other way, such as taking their addresses.

CRTP pattern doesn't trigger full template instantiation

I've created a template class which triggers a runtime text output whenever an instantiation of it occurs:
template<typename T>
struct verbose {
verbose()
{
std::cout << "Instantation occured!" << std::endl;
}
};
template<typename T>
struct base
{
inline static verbose<T> v;
};
When I force to create instantiation, it shows an output:
template struct base<int>;
//output: Instantation occured!
(Check on Wandbox).
On the other hand, when I use it with a CRTP pattern, it seems that instantiation does not occur:
class test : public base<test>
{
};
(Check on Wandbox)
Is this behavior OK with the ISO standard? Can I somehow force to make instantiation, without requiring users of my template class (base) to write additional code? For me, the important thing is the side effect of the static variable constructor.
Your CRTP usage falls under implicit instantiation:
When code refers to a template in context that requires a completely defined type, or when the completeness of the type affects the code, and this particular type has not been explicitly instantiated, implicit instantiation occurs. For example, when an object of this type is constructed, but not when a pointer to this type is constructed.
This applies to the members of the class template: unless the member is used in the program, it is not instantiated, and does not require a definition.
cppreference
Following the second paragraph, since base<test>::v is never actually used, no instantiation of base<test>::v actually occurs.
Since a usage is required to generate its instantiation, there will need to be additional code to get your desired output. For example, you could add a constructor to base:
template<typename T>
struct base
{
inline static verbose<T> v;
base() { (void)&v; }
};
This alone is not enough to trigger your output based on the definition of test by itself. However, if your program tries to create an object from test, then the formation of the constructor will cause the template's constructor to be used, and thus base<test>::v will be instantiated.

Is dynamic instantiation of a class template considered as explict or implicit?

If I have a class template and I use a smart pointer to a dynamically allocated instance of a specialized instance, does that cause the entire class template to be defined by the complier or will it also wait for a member function to be called from the pointer before it is instantiated?
template <class T>
class Test {
public:
void nothing();
void operation();
static const int value;
};
template <class T>
const int Test<T>::value = 100;
template <class T>
void Test<T>::nothing() {
/* invalid code */
int n = 2.5f;
}
template <class T>
void Test<T>::operation() {
double x = 2.5 * value;
}
int main() {
std::unique_ptr<Test<int>> ptr = new Test<int>(); // mark1
ptr->operation(); // mark2
return 0;
}
Does the entire class template get instantiated at mark1?
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
Does the entire class template get instantiated at mark1?
Yes. The class template is implicitly instantiated — only the class template, not all its members.
If not does that mean this code will compile correctly and the member function Test::nothing() not be instantiated?
The not doesn't imply that, rather if nothing() is not used, it is not instantited.
The full answer to this probably depends highly on what compiler you are using.
At //mark1, the compiler will notice that at least portions of the Test<int> class need to instantiated. Whether or not it does it right then, or in a later phase, is up to the compiler designer.
At //mark2, Test<int>.operation() is obviously needed, it is either marked for later instantiation or created on the spot, again depending on what the compiler designers decided.
Since Test<int>.nothing() is never referenced, the compiler has the freedom to instantiate it or not. Some older compilers blindly instantiated the entire class, but I suspect the majority of modern compilers will only instantiate what they can prove to be necessary (or at least that they can't prove is not necessary). Again, though, where that happens within the compiler depends on the way the compiler designers built the compiler.
So as it turns out for the compiler I'm using (MS Visual C++), my supposition was correct that, for the code as presented in the question, the class template member instantiation would not take place at //mark1 but rather at //mark2 and Test<int>.nothing() would not be created by the compiler.
However, it seems I left out a critical part of the issue that I was experiencing. My actual class was a part of a virtual hierarchy, and according to the MSDN help library all virtual members are instantiated at object creation. So in the example above, if both member functions, i.e. operation() and nothing(), are virtual then at //mark2 the compiler would try to generate code for both functions and the validation of nothing() would fail.
http://msdn.microsoft.com/en-us/library/7y5ca42y.aspx
http://wi-fizzle.com/howtos/vc-stl/templates.htm#t9

Is it valid for a C++ compiler to implicitly instantiate ALL member functions of a template class?

Suppose I have a public class and a private implementation class (e.g. PIMPL pattern), and I wish to wrap the private class with a template smart pointer class with a checked delete, as follows:
PublicClass.h
class PrivateClass;
// simple smart pointer with checked delete
template<class X> class demo_ptr
{
public:
demo_ptr (X* p) : the_p(p) { }
~demo_ptr () {
// from boost::checked_delete: don't allow compilation of incomplete type
typedef char type_must_be_complete[ sizeof(X)? 1: -1 ];
(void) sizeof(type_must_be_complete);
delete the_p;
}
private:
X* the_p;
};
// public-facing class that wishes to wrap some private implementation guts
class PublicClass
{
public:
PublicClass();
~PublicClass();
private:
demo_ptr<PrivateClass> pvt;
};
PublicClass.cpp
#include "PublicClass.h"
class PrivateClass
{
public:
// implementation stuff goes here...
PrivateClass() {}
};
//---------------------------------------------------------------------------
PublicClass::PublicClass() : pvt(new PrivateClass()) {}
PublicClass::~PublicClass() {}
main.cpp
#include "PublicClass.h"
int main()
{
PublicClass *test = new PublicClass();
delete test;
return 0;
}
This code compiles successfully on Visual C++ 2008, but fails to compile on an old version of C++ Builder. In particular, main.cpp does not compile because demo_ptr<PrivateClass>::~demo_ptr is being instantiated by main.cpp, and that destructor won't compile because it can't do sizeof on an incomplete type for PrivateClass. Clearly, it is not useful for the compiler to be instantiating ~demo_ptr in the consuming main.cpp, since it will never be able to generate a sensible implementation (seeing as how ~PrivateClass is not accessible). (PublicClass.cpp compiles fine on all tested compilers.)
My question is: what does the C++ standard say about implicit instantiation of a template class's member functions? Might it be one of the following? In particular, has this changed over the years?
If a template class is used, then all member functions of the class should be implicitly instantiated - whether used or not?
Or: template class functions should only be implicitly instantiated one at a time if actually used. If a particular template class function isn't used, then it shouldn't be implicitly instantiated - even if other template class functions are used and instantiated.
It seems clear that the second case is the case today because this same pattern is used with PIMPL and unique_ptr with its checked delete, but maybe that was not the case in the past? Was the first case acceptable compiler behavior in the past?
Or in other words, was the compiler buggy, or did it accurately follow the C++98 standard, and the standard changed over the years?
(Fun fact: if you remove the checked delete in C++ Builder, and have function inlining turned off, the project will happily compile. PublicClass.obj will contain a correct ~demo_ptr implementation, and main.obj will contain an incorrect ~demo_ptr implementation with undefined behavior. The function used will depend on the order in which these files are fed to the linker.)
UPDATE: This is due to a compiler bug, as noted by Andy Prowl, which is still not fixed in C++ Builder XE8. I've reported the bug to Embarcadero: bcc32 compiler causes undefined behavior when using std::auto_ptr with PIMPL idiom because template instantiation rules do not follow C++ spec
If a template class is used, then all member functions of the class should be implicitly instantiated - whether used or not?
No, this is definitely not the case. Per Paragraph 14.7.1/10 of the C++11 Standard (and Paragraph 14.7.1/9 of the C++03 Standard) very clearly specifies:
An implementation shall not implicitly instantiate a function 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.
As for when instantiation is required, Paragraph 14.7.1/2 specifies:
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; [...]
This is certainly not the case if a member function is never referenced.
Unfortunately, I can't provide an official reference on what the rules were before C++03, but to the best of my knowledge the same "lazy" instantiation mechanism was adopted in C++98.
unique_ptr is a funny beast.
Unlike auto_ptr, which called the destructor of the referenced object from the smart pointer destructor, unique_ptr::~unique_ptr merely invokes a deleter function which has been previously stored.
The deleter function is stored in the unique_ptr constructor, which is called for each and every PublicClass constructor. The user-defined constructor is defined in a context where PrivateClass::~PrivateClass is available, so that's ok. But what about other implicitly-generated PublicClass constructors, such as a move constructor? They're generated at the point of use; they also need to initialize the unique_ptr member, meaning they must supply a deleter. But without PrivateClass::~PrivateClass, they can't.
Wait, your question mentions unique_ptr, but your code isn't using it. Weird...
Even when the destructor is invoked from the smart pointer destructor, it can still be ODR-used from the containing class constructors. This is for exception-safety -- the constructor needs the capability to tear down a partially-constructed class, which includes destruction of members.
It looks like C++Builder may be generating a PublicClass copy or more constructor, even though your program doesn't use it. That doesn't fall afoul of the rule Andy mentioned, because PublicClass isn't a template. I think the compiler is entitled to generate a defaulted copy constructor for PublicClass when it processes the class definition, since you can't provide an out-of-class definition for a defaulted member. Respecting the rule of three for demo_ptr will preclude PublicClass having a copy constructor, and therefore may solve your problem.

Marking function as virtual causes compiler error with unique_ptr

I have a templated class that wraps a vector. I'm trying to store unique_ptrs in this class, and it works fine. However, when I mark the void add(const T& elem) function as virtual, my compiler (clang) tells me that I'm making a "call to implicitly-deleted copy constructor" for unique_ptr.
I understand that unique_ptrs can't be copied, so that's why I created the void add(T&& elem) function. I just don't know why marking the other add function as virtual causes the compiler error.
Thanks for your time.
#include <iostream>
#include <vector>
#include <memory>
using namespace std;
template <typename T>
class ContainerWrapper {
private:
vector<T> vec;
public:
ContainerWrapper() : vec() {
}
//Marking this as virtual causes a compiler error
void add(const T& elem) {
vec.push_back(elem);
}
void add(T&& elem) {
vec.push_back(std::move(elem));
}
T removeLast() {
T last = std::move(vec.back());
vec.pop_back();
return last;
}
};
int main() {
ContainerWrapper<unique_ptr<string>> w;
w.add(unique_ptr<string>(new string("hello")));
unique_ptr<string> s = w.removeLast();
cout << *s << endl;
}
This is most likely due to ContainerWrapper being a template. With templates, the compiler most often won't even check member functions as long as you don't call them. However, marking it virtual forces the function to be present (you might also even get a link error).
You can possibly take a look at this post : When the virtual member functions of a template class instantiated?.
The problem here is that std::unique_ptr has its copy constructor marked as =delete. This means that the vec.push_back(elem) call inside the add(T const&) overloaded member function will not compile when being called with a std::unique_ptr. The compiler will realize this as soon as that member function is being instantiated.
The Standard has 2 relevant quotes here in 14.7.1 Implicit instantiation [temp.inst]:
6 If the overload resolution process can determine the correct
function to call without instantiating a class template definition, it
is unspecified whether that instantiation actually takes place.
10 [...] It is unspecified whether or not an implementation implicitly
instantiates a virtual member function of a class template if the
virtual member function would not otherwise be instantiated. [...]
Clause 6 states that -without the virtual keyword- the compiler is allowed but not required to instantiate both add(T const&) and add(T&&) in order to resolve which overload is the best match. Neither gcc 4.7.2 nor Clang 3.2 need the instantiation because they happen to deduce that rvalue references always are a better match for temporaries than lvalue references.
Clause 10 states that -even with the virtual keyword- the compiler is also allowed but not required to instantiate add(T const&) and add(T&&) in order to resolve which overload is the best match. Both gcc 4.7.2 and Clang 3.2 happen to the instantiate both member functions, even though they both could have deduced that the lvalue overload would never be a better match.
Note that if you make ContainerWrapper a regular class with a nested typedef unique_ptr<string> T;, then both gcc and Clang will generate errors with or without the virtual keyword because they have to generate code for both member functions. This will not be SFINAE'ed away because it the error does not happen during substitution of deduced arguments.
Conclusion: this is not a bug but a quality of implementation issue.