Here's my attempt:
Foo
template class and declaring but not defining a ctor only for a given value of the NTTP N
,
// foo.hpp
#include <type_traits>
template<int N>
struct Foo {
template<int M = N, std::enable_if_t<M == 2, int> = 0>
Foo(int);
};
Foo
for a value that corresponds to the ctor not being SFINAEd out,
// foo.cpp
#include "foo.hpp"
template<int N>
template<int M, std::enable_if_t<M == 2, int>>
Foo<N>::Foo(int) {}
template struct Foo<2>;
Foo<2>
class,
// main.hpp
#include "foo.hpp"
int main() {
Foo<2>{0};
}
If I try to compile the two TUs above and link them, I get the following error from the linker:
main.cpp:(.text+0x24): undefined reference to `Foo<2>::Foo<2, 0>(int)'
collect2: error: ld returned 1 exit status
Indeed, I don't see any symbols from foo.cpp
, as this
nm foo.o
gives no output.
If I add another, un-constrained ctor, e.g.
// foo.hpp
// …
struct Foo {
Foo(int, int);
// …
and
// foo.cpp
// …
template<int N>
Foo<N>::Foo(int, int) {}
// …
then I do get what I expect:
nm foo.o | c++filt
0000000000000000 W Foo<2>::Foo(int, int)
0000000000000000 W Foo<2>::Foo(int, int)
0000000000000000 n Foo<2>::Foo(int, int)
Explicitly instantiate template class doesn't instantiate template member function.
You need to explicitly instantiate those methods too:
// template Foo<2>::Foo<2, 0>(int); // Not supported by clang
template Foo<2>::Foo(int);