Наименьший воспроизводимый код:
#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)