最小的可重现代码是:
#include <map>
template <class T, class T2>
struct relative_iterator : T {};
struct edge : public std::map<int, int>::iterator {};
using T_edge = edge;
class node {
public:
template <class T_iterable, class T_content>
class sibling_iterator : public relative_iterator<T_iterable, T_content>
{
public:
friend sibling_iterator<edge, T_edge> node::leftmost_output();
//..
};
static sibling_iterator<edge, T_edge> leftmost_output(); // <--move up
} ;
有两种方法可以解决这个问题:
选项 1
将leftmost_output()的定义移到class sibling_iterator上方
选项 2
将node 设为从属名称。如果name 的别名依赖于T_iterable,则其查找将延迟到class sibling_iterator<T_iterable, T_contents> 实例化的时间。最简单的方法是使用标准中的标准实用程序:
class sibling_iterator : public relative_iterator<T_iterable, T_content>
{
public:
static constexpr bool dependent_true = std::is_same<T_iterable,T_iterable>::value;
using dependent_node = typename std::enable_if<dependent_true, node>::type;
friend sibling_iterator<edge, T_edge> dependent_node::leftmost_output();
};
选项 2.5
但是,如果您更喜欢定义自己的解决方案,您可以定义一个dependet_type<T, Dependent> 助手:
template <class T, class Dependent>
struct dependent_type
{
using type = T;
};
template <class T, class Dependent>
using dependent_type_t = typename dependent_type<T, Dependent>::type;
并使用它:
template <class T_iterable, class T_content>
class sibling_iterator : public relative_iterator<T_iterable, T_content>
{
public:
using dependent_node = typename dependent_type<node, T_iterable>::type;
friend sibling_iterator<edge, T_edge> dependent_node::leftmost_output();
//..
};
我认为这是最好的选择,因为它需要对现有代码库进行较少的更改。
选项 2.5.5
我会写一个更短的变体:
friend sibling_iterator<edge, T_edge> dependent_type_t<node, T_iterable>::leftmost_output()
这看起来很完美,因为它只需要对源代码进行最少的更改。如果它没有导致编译器崩溃,我会写的:
fatal error C1001: An internal error has occurred in the compiler.
(compiler file 'msc1.cpp', line 1469)