Can we see the template instantiated code by C++ compiler
You can definitely see the assembly code generated by the g++ using the "-S" option.
I don't think it is possible to display the "C++" equivalent template code - but I would still want a g++ developer to chime in why - I don't know the architecture of gcc.
When using assembly, you can review the resulting code looking for what resembles your function. As a result of running gcc -S -O1 {yourcode.cpp}, I got this (AMD64, gcc 4.4.4)
_Z3addIiET_S0_S0_:
.LFB2:
.cfi_startproc
.cfi_personality 0x3,__gxx_personality_v0
leal (%rsi,%rdi), %eax
ret
.cfi_endproc
Which really is just an int addition (leal).
Now, how to decode the c++ name mangler? there is a utility called c++filt, you paste the canonical (C-equivalent) name and you get the demangled c++ equivalent
qdot@nightfly /dev/shm $ c++filt
_Z3addIiET_S0_S0_
int add<int>(int, int)
Template instantiation details of GCC and MS compilers
Point of instantiation
templates will be instantiated when actually used
Not exactly, but roughly. The precise point of instantiation is a bit subtle, and I delegate you over to the section named Point of instantiation in Vandevoorde's/Josuttis' fine book.
However, compilers do not necessarily implement the POIs correctly: Bug c++/41995: Incorrect point of instantiation for function template
Partial instantiation
templates will be instantiated when actually used
That is partially correct. It is true for function templates, but for class templates, only the member functions that are used are instantiated. The following is well-formed code:
#include <iostream>
template <typename> struct Foo {
void let_me_stay() {
this->is->valid->code. get->off->my->lawn;
}
void fun() { std::cout << "fun()" << std::endl; }
};
int main () {
Foo<void> foo;
foo.fun();
}
let_me_stay()
is checked syntactically (and the syntax there is correct), but not semantically (i.e. it is not interpreted).
Two phase lookup
However, only dependent code is interpreted later; clearly, within Foo<>
, this
is dependent upon the exact template-id with which Foo<>
is instantiated, so we postponed error-checking of Foo<>::let_me_alone()
until instantiation time.
But if we do not use something that depends on the specific instantiation, the code must be good. Therefore, the following is not well-formed:
$ cat non-dependent.cc
template <typename> struct Foo {
void I_wont_compile() { Mine->is->valid->code. get->off->my->lawn; }
};
int main () {} // note: no single instantiation
Mine
is a completely unknown symbol to the compiler, unlike this
, for which the compiler could determine it's instance dependency.
The key-point here is that C++ uses a model of two-phase-lookup, where it does checking for non-dependent code in the first phase, and semantic checking for dependent code is done in phase two (and instantiation time) (this is also an often misunderstood or unknown concept, many C++ programmers assume that templates are not parsed at all until instantiation, but that's only myth coming from, ..., Microsoft C++).
Full instantiation of class templates
The definition of Foo<>::let_me_stay()
worked because error checking was postponed to later, as for the this
pointer, which is dependent. Except when you would have made use of
explicit instantiations
cat > foo.cc
#include <iostream>
template <typename> struct Foo {
void let_me_stay() { this->is->valid->code. get->off->my->lawn; }
void fun() { std::cout << "fun()" << std::endl; }
};
template struct Foo<void>;
int main () {
Foo<void> foo;
foo.fun();
}
g++ foo.cc
error: error: ‘struct Foo<void>’ has no member named ‘is’
Template definitions in different units of translation
When you explicitly instantiate, you instantiate explicitly. And make all symbols visible to the linker, which also means that the template definition may reside in different units of translation:
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<void>().fun();
}
$ cat B.cc
#include <iostream>
template <typename> struct Foo {
void fun();
};
template <typename T>
void Foo<T>::fun() {
std::cout << "fun!" << std::endl;
} // Note: definition with extern linkage
template struct Foo<void>; // explicit instantiation upon void
$ g++ A.cc B.cc
$ ./a.out
fun!
However, you must explicitly instantiate for all template arguments to be used, otherwise
$ cat A.cc
template <typename> struct Foo {
void fun(); // Note: no definition
};
int main () {
Foo<float>().fun();
}
$ g++ A.cc B.cc
undefined reference to `Foo<float>::fun()'
Small note about two-phase lookup: Whether a compiler actually implements two-phase lookup is not dictated by the standard. To be conformant, however, it should work as if it did (just like addition or multiplication do not necessarily have to be performed using addition or multiplication CPU instructions.
Where are template functions instantiated?
In what object file is
func<int>
instantiated?
In every object file (aka translation unit) that invokes it or takes an address of it when the template definition is available.
Why will the One Definition Rule not be violated?
Because the standard says so in [basic.def.odr].13.
Also see https://en.cppreference.com/w/cpp/language/definition
There can be more than one definition in a program of each of the following: class type, enumeration type, inline function, inline variable (since C++17), templated entity (template or member of template, but not full template specialization), as long as all of the following is true...
For this basic application of templates, is there any benefit to explicitly instantiating
func<int>
separate from its use?
In this case you get no inlining but possibly smaller code. If you use link-time code generation, then inlining may still happen.
Is it possible to view C++ code with instantiated templates before it gets compiled (g++)?
Well, the closer you can get is to read the AST/ABT generated by the compiler:
- AST: Abstract Syntax Tree
- ABT: Abstract Binding Tree
The former represents the view of the syntax as the compiler understands it and the latter is similar after resolution of the bindings (ie, that the a
here is actually the variable that was declared 3 lines before or that the foo
correspdonds to the function defined in that header...).
Clang allows to dump its AST... which is in fact the ABT, actually, it's being improved at this very moment; sneak developer preview:
int Test __attribute__((visibility("default")));
int main(int argc, char** argv) {
int x __attribute__((aligned(4))) = 5;
int y = 2;
for (;;)
if (x != y++)
break;
return (x * y);
}
Normally you should see how the template was instantiated there.
Note: to get it you need the -ast-dump
pass to the clang front-end.
How to instantiate, by the standard, a class template containing nested subclass templates
There's a few things going wrong here:
template <class C> struct MyData : Data<C> {
MyData::Item1<int> item10;
};
MyData
is an incomplete type here, so we can't use it just yet in that way. However, since Item1
is inherited from Data<C>
, we should be able to just refer to it directly:
Data<C>::Item1<int> item10;
But now, Data<C>::Item1
is a dependant type, so we need to use typename
to tell the compiler that it is, in fact, a type:
typename Data<C>::Item1<int> item10;
Finally, because Item1
is a template member of a dependant type, we also need to tell the compiler that it is a template (as opposed to a constant or something).
typename Data<C>::Item1 template<int> item10;
So at the end, we land at:
template<class C> struct Data {
template<typename T> struct Item1 {
void Test() {
}
};
};
template <class C>
struct MyData : Data<C> {
typename Data<C>::template Item1<int> item10;
};
struct S;
MyData<S> dataS;
Detect the existence of a template instantiation for a given type
Here's a link-time solution. Works on GCC, Clang, and MSVC.
One template (impl::Checker<T>
) declares a friend function and calls it.
Another template (impl::Marker
) defines that function. If it's not defined, the first class gets an undefined reference.
run on gcc.godbolt.org
#include <cstddef>
#include <type_traits>
namespace impl
{
template <typename T>
struct Checker
{
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-template-friend"
#endif
friend void adl_MarkerFunc(Checker<T>);
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
static std::nullptr_t Check()
{
adl_MarkerFunc(Checker<T>{});
return nullptr;
}
inline static const std::nullptr_t check_var = Check();
static constexpr std::integral_constant<decltype(&check_var), &check_var> use_check_var{};
};
template <typename T>
struct Marker
{
friend void adl_MarkerFunc(Checker<T>) {}
};
}
template <typename T, impl::Checker<T> = impl::Checker<T>{}>
struct Access
{
template <typename U>
void Read()
{
static_assert(std::is_same_v<T, U>);
(void)impl::Marker<U>{};
}
};
int main()
{
Access<int> x;
x.Read<int>();
[[maybe_unused]] Access<float> y; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<float>)'
using T [[maybe_unused]] = Access<double>; // undefined reference to `impl::adl_MarkerFunc(impl::Checker<double>)'
}
Had to introduce a dummy template parameter to Access
, since I couldn't think of any other way of detecting it being used in a using
.
Related Topics
Constructor Invocation Mechanism
How to Pause a Pthread Any Time I Want
Loop Until Integer Input Is in Required Range Fails to Work with Non-Digit Character Inputs
Matlab VS C++ VS Opencv - Imresize
Opencv Unable to Set Up Svm Parameters
Unresolved Externals in C++ When Using Vectors and Find
Why Does This Code with '1234' Compile in C++
Why Callback Functions Needs to Be Static When Declared in Class
Is Circumventing a Class' Constructor Legal or Does It Result in Undefined Behaviour
How to Use Std::Filesystem on Gcc 8
C++ Function Callbacks: Cannot Convert from a Member Function to a Function Signature
Compiling a Simple Parser with Boost.Spirit
Errors When Linking to Protobuf 3 on Ms Visual C
How to Use Sort() in C++ with Custom Sort Member Function
How to Check That an Element Is in a Std::Set