Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward-declaring template variable in C++

The forward-declaring template variable will cause ld error.

#include <iostream>
template<class T> extern int a;
template<class T> int a = 1;
int main()
{
    std::cout << a<int> << a<float>;
    return 0;
}
$ LANG=C g++ main.cpp -o main
/usr/bin/ld: /tmp/cccOb25F.o: in function `main':
main.cpp:(.text+0x6): undefined reference to `a<int>'
/usr/bin/ld: main.cpp:(.text+0x1d): undefined reference to `a<float>'
collect2: error: ld returned 1 exit status

However, the forward-declaring variable (without template) and the forward-declaring template function works fine.

#include <iostream>
extern int a;
int a = 1;
template<class T> int b();
template<class T> int b()
{
    return 2;
}
int main()
{
    std::cout << a << b<int>();
    return 0;
}

So, is it possible to make the forward-declaring template variable in C++ works?

EDIT:

Since clang++ works fine, maybe I accidentally found a bug of g++?

EDIT2:

I have found a bug report about 2.5 years ago (here), which is exactly the same problem. Oh, we need a guy who could read gcc source and fix it...

like image 790
陈浩南 Avatar asked Jul 23 '20 10:07

陈浩南


People also ask

Can you forward declare a template?

You can declare default arguments for a template only for the first declaration of the template. If you want allow users to forward declare a class template, you should provide a forwarding header. If you want to forward declare someone else's class template using defaults, you are out of luck!

What is forward declaration in C?

In computer programming, a forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

What is function forward declaration?

A forward declaration allows us to tell the compiler about the existence of an identifier before actually defining the identifier. In the case of functions, this allows us to tell the compiler about the existence of a function before we define the function's body.

How a template is declared?

A class template must be declared before any instantiation of a corresponding template class. A class template definition can only appear once in any single translation unit. A class template must be defined before any use of a template class that requires the size of the class or refers to members of the class.


1 Answers

Open GCC Bug Report 83342 - "extern marked variable template with later definition emits error"

This is GCC Bug 83342, which is yet to be addressed.

GCC seems to make, whether intentionally or not, the assumption that a variable template first declared with the extern keyword in a given translation unit (TU) must have its definition in another TU (thus not even looking for it in the same TU). E.g. Clang does not make this assumption (and finds the definition and re-declaration in the same TU).

template<class T> extern int a;      // extern declaration.
template<class T>        int a = 1;  // definition.
template int a<int>;  // explicit instantiation definition for a<int> specialization.

// Clang: OK
// GCC:
// - error: explicit instantiation of 'a<int>' but no definition available

int main() {}

There is no clause in the standard that would allow the assumption that GCC makes above, and the open bug report is valid.

We may note that GCC accepts the similar and likely much more common case for function templates:

template<class T> extern void f();    // extern declaration.
template<class T>        void f() {}  // definition.
template void f<int>();  // explicit instantiation definition for f<int>() specialization.

// Clang: OK
// GCC:   OK

int main() {}
like image 178
dfrib Avatar answered Nov 15 '22 05:11

dfrib