In the code below, I am getting
main.cpp: undefined reference to `(anonymous namespace)::_result<int, double>::type
PPP<int>::operator()<double>(double const&) const'
even though that template is explicitly instanciated. The code hase 3 modules: man.cpp
uses PPP<type>
, ppp.cpp
explicit instanciates PPP<int>
and PPP<double>
, and aaa.cpp
instanciates a method template.
Sorry for the lengthy test case, I couldn't get it shorter, and it appears the result_type
template is needed for the fail.
ppp.h
#include <type_traits>
namespace
{
template<typename T> struct _prio {};
template<> struct _prio<int> { using type = std::integral_constant<int,1>; };
template<> struct _prio<double> { using type = std::integral_constant<int,2>; };
template<typename A, typename X>
struct _result
{
static constexpr bool cond = _prio<A>::type::value > _prio<X>::type::value;
using type = typename std::conditional<cond, A, X>::type;
};
} // ::anon
template<typename T>
struct PPP
{
template<typename X>
using result_type = typename _result<T,X>::type;
T t;
T operator () (const T&) const;
// aaa.cpp contains an explicit instanciation for T=int, X=double
// which is used in main().
template<typename X>
result_type<X> operator () (const X&) const;
};
// Instanciated in ppp.cpp
extern template struct PPP<int>;
extern template struct PPP<double>;
ppp.cpp
#include "ppp.h"
template<typename T>
T PPP<T>::operator () (const T& s) const
{
return s + t;
}
template struct PPP<int>;
template struct PPP<double>;
aaa.cpp
#include "ppp.h"
template<class T>
template <class X>
auto PPP<T>::operator () (const X& x) const -> result_type<X>
{
return x - (X) t;
}
extern template
auto PPP<int>::operator () (const double&) const -> result_type<double>;
template
auto PPP<int>::operator () (const double&) const -> result_type<double>;
main.cpp
#include "ppp.h"
#include <iostream>
extern template
auto PPP<int>::operator () (const double&) const -> result_type<double>;
int main (void)
{
PPP<int> pi { 10 };
std::cout << pi.t << std::endl;
std::cout << pi (22) << std::endl;
// Triggers with g++ v11.4, but not with clang++
// main.cpp: undefined reference to `(anonymous namespace)::_result<int, double>::type
// PPP<int>::operator()<double>(double const&) const'
std::cout << pi (33.3) << std::endl;
return 0;
}
compile
$ <compiler> main.cpp ppp.cpp aaa.cpp -o main.x -Wall
Where <compiler>
is one of g++
or clang++
. With clang, it compiles and links fine, but with g++ v11.4 the linker complains
/usr/bin/ld: in function `main':
main.cpp: undefined reference to `(anonymous namespace)::_result<int, double>::type
PPP<int>::operator()<double>(double const&) const'
collect2: error: ld returned 1 exit status
When I am adding -save-temps -dumpbase ""
to g++ options, and then cat aaa.s | c++filt
, the definition of the method can be seen, but it is neither .global
nor .weak
. And with -O2
the method is no more present. With clang++ it is .weak
and thus visible.
So can someone explain what I am missing?
Aucun commentaire:
Enregistrer un commentaire