C++ template: no compile error although an error is present

79 views Asked by At

can someone please shed some light on a curious phenomenon with C++ templates. Consider this simple code:

class B {};

template <typename T>
class A 
{
    T _v;
public:
    A() {}
    void add(T a) { _v += a; }
};

int main()
{
    A<B> b;
    return 0;
}

Clearly this isn't legal because the += operator is not defined for class B, and therefore the code inside the add method is invalid. Yet this code compiles fine!

It is not until you call the add method that you get a compile error:

int main()
{
    A<B> b;
    b.add(B()); // complains about a missing += operator
    return 0;
}

For a non-template class the compile error occurs regardless of whether the class is used at all.

class C
{
    B _v;
public:
    C() {}
    void add(B a) { _v += a; } // compile error here right away
};

Why is that? Thanks.

1

There are 1 answers

0
Vlad from Moscow On

If a member function of a class template is not used it is not instantiated.

In the second program the member functon of the class template A is used and the compiler tries to instantiate it. As a result it issues an error.

From the C++20 Standard (13.9.2 Implicit instantiation)

3 The implicit instantiation of a class template specialization causes

(3.1) — the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and

(3.2) — the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.

And there is an example

[Example 3 :

template<class T>
struct C {
    void f() { T x; }
    void g() = delete;
};
C<void> c; // OK, definition of C<void>::f is not instantiated at this point
template<> void C<int>::g() { } // error: redefinition of C<int>::g

— end example]

Such an approach allows to reduce the compilation time. You don't pay for what you don't use.