У меня есть следующий сценарий:
template<typename Derived, typename ValType>
class foo
{
public:
template<typename R>
bar<typename std::vector<R>::const_iterator> select()
{
std::vector<R> translation;
return bar<typename std::vector<R>::const_iterator>(std::move(translation));
}
};
template<typename T>
class bar
: public foo<bar<T>, typename std::iterator_traits<T>::value_type>
{
public:
bar(std::vector<typename std::iterator_traits<T>::value_type>&& vec)
{
}
};
По сути, это небольшое подтверждение концепции, с которой я играю, используя CRTP, а foo — миксин.
Проблема в том, что я считаю, что должен использовать предварительную декларацию, однако я попробовал следующее:
class bar; // I didn't expect this to work
Однако я ожидал, что это сработает:
template<typename R>
class bar;
который прекрасно компилируется, пока я не вызову select ()
std::vector<int> enumerable_vector;
enumerable_vector.push_back(1);
enumerable_vector.push_back(2);
bar<typename std::vector<int>::const_iterator> baz(std::move(enumerable_vector));
baz.select<std::string>();
что приводит к следующей ошибке: —
Ошибка C2027: использование неопределенного типа
‘Foo :: Бар’
Любая помощь будет признательна, спасибо!
Ошибка C2027: использование неопределенного типа ‘foo :: bar’
Кажется, сообщение об ошибке указывает на то, что вы перенаправили объявленный вложенный тип bar
в foo
, Вы должны заранее объявить правильный тип (переместить объявление bar
на уровне пространства имен только над определением foo
)
РЕДАКТИРОВАТЬ: Этот ответ неверен. bar
не должно быть полным, когда select
является определенный, должно быть завершено, когда select
является инстанцирован. Перемещение определения select
вне строки после спецификатора класса для bar
не обязательно.
Проблема в том, что ваше определение select
внутри спецификатора класса для foo
требует bar
быть завершенным. Если вы перешлите объявить bar
и только объявлять select
в спецификаторе класса вы можете переместить определение select
вне линии к где bar
завершено. Затем он компилируется нормально:
#include <iterator>
#include <utility>
#include <vector>
template<typename T> class bar;
template<typename Derived, typename ValType>
class foo
{
public:
template<typename R>
bar<typename std::vector<R>::const_iterator> select();
};
template<typename T>
class bar
: public foo<bar<T>, typename std::iterator_traits<T>::value_type>
{
public:
bar(std::vector<typename std::iterator_traits<T>::value_type>&& vec)
{
}
};
template<typename Derived, typename ValType>
template<typename R>
bar<typename std::vector<R>::const_iterator> foo<Derived, ValType>::select()
{
std::vector<R> translation;
return bar<typename std::vector<R>::const_iterator>(std::move(translation));
}