Using Variant and Visitor idioms for dealing with abstract syntax tree of mathematical expression I faced linker errors undefined reference to 'function_name'
prepended with warnings inline function 'function_name' is not defined [-Wundefined-inline]
, where function_name
is all possible names of specializations (i.e. for B
and for C
) of function marked // 1
below (live example):
#include <type_traits>
#include <utility>
#include <iostream>
#include <boost/variant.hpp>
#include <cstdlib>
namespace
{
struct A {};
struct B {};
struct C {};
using V = boost::variant< A, B, C >;
struct visitor
{
using result_type = void;
result_type
operator () (V v) const
{
#if 1
return boost::apply_visitor([this] (auto && x) -> result_type { return apply(std::forward< decltype(x) >(x)); }, v);
}
#else
return boost::apply_visitor(*this, v);
}
template< typename T >
result_type
operator () (T && x) const
{
return apply(std::forward< T >(x));
}
#endif
private :
result_type
apply(A) const
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template< typename T >
result_type
apply(T &&) const // 1
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
public : // !
};
}
int
main()
{
visitor{}(V{B{}});
return EXIT_SUCCESS;
}
Frankly, warning message here is function 'function_name' has internal linkage but is not defined [-Wundefined-internal]
, but if we split above code into header and .cpp
files, then message would be exactly as one mentioned above.
If I change #if 0
to #if 1
, then all compiles fine. Another note is: when I move result_type operator () (V v) const
to second public
section (marked // !
), then all compiles fine too.
Seems lambda makes something subtle with instantiation of function template defined strictly below definition of lambda.
How to explain above behaviour and difference in behaviour of lambda version and version with visitor &
passed to boost::apply_visitor
?
Real-life example is here.
Aucun commentaire:
Enregistrer un commentaire