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 (header):
#pragma once
#include <utility>
#include <iostream>
#include <boost/variant.hpp>
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
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
public : // !
};
(main.cpp):
#include "implementation.hpp"
#include <cstdlib>
int
main()
{
visitor{}(V{B{}});
return EXIT_SUCCESS;
}
Here is live example: main.cpp and header files. If contents of header file moved to main.cpp
, then warning changed to function 'function_name' has internal linkage but is not defined [-Wundefined-internal]
. But I am sure the sources of errors are exactly the same.
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