考虑到一个过时的简化代码(我不知道如何减少它):
#include <type_traits>
#include <iostream>
#include <cstdlib>
#define PP { std::cout << __PRETTY_FUNCTION__ << std::endl; }
struct descriptor
{
std::size_t const s;
bool const * c;
bool const * d;
};
template< descriptor const & x, bool c, bool d, typename ...types >
union U;
template< descriptor const & x, bool c, bool d >
union U< x, c, d >
{
static_assert(c);
static_assert(d);
U() PP
~U() PP
};
template< descriptor const & x, bool c, bool d, typename first, typename ...rest >
union U< x, c, d, first, rest... > // specialize against c and/or d values
{
static constexpr std::size_t s = x.s - sizeof...(rest);
using tail = U< x, x.c[s], x.d[s], rest... >;
first head_;
tail tail_{};
U() PP
~U() { PP; /*tail_.~tail();*/ } // !!!!!!!
};
template< typename ...types >
struct V
{
static constexpr bool c[sizeof...(types) + 1] = {std::is_trivially_constructible< types >{}..., true};
static constexpr bool d[sizeof...(types) + 1] = {std::is_trivially_destructible< types >{}..., true};
static constexpr descriptor x{sizeof...(types), c, d};
U< x, x.c[0], x.d[0], types... > storage_;
V() PP
~V() PP
};
template< typename ...types >
constexpr bool V< types... >::c[sizeof...(types) + 1];
template< typename ...types >
constexpr bool V< types... >::d[sizeof...(types) + 1];
template< typename ...types >
constexpr descriptor V< types... >::x;
int
main()
{
struct S { S() { ; } ~S() { ; } };
V< int, S, double > v;
(void)v;
S s;
(void)s;
return EXIT_SUCCESS;
}
它的作用是通过递归union
传播类型特征,以便在递归深度的某处使用它们。
目前,代码提供了链接器错误:
/tmp/main-ecd8fb.o: In function `main':
main.cpp:(.text+0x2fa): undefined reference to `_ZN1UIL_ZN1VIJiZ4mainE1SdEE1xEELb1ELb1EJEED1Ev'
main.cpp:(.text+0x318): undefined reference to `_ZN1UIL_ZN1VIJiZ4mainE1SdEE1xEELb1ELb1EJdEED1Ev'
main.cpp:(.text+0x336): undefined reference to `_ZN1UIL_ZN1VIJiZ4mainE1SdEE1xEELb0ELb0EJS1_dEED1Ev'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
但如果我取消注释感叹号标记的行,则liker错误不再存在。这很奇怪,因为这样做我开始使用更多的符号,然后。 | c++filt -t
无法解除这些符号,我无法推断出错了什么。是clang
(版本3.7.0)错误还是ld
(GNU ld v2.22)错误或其他什么?一般如何检测此类错误的来源?你使用哪些工具?