2014-01-10 2 views
1

У меня есть следующий сценарий: -декларация вперед класса с шаблоном, используя имя типа

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 быть Mixin.

Проблема заключается в том, что я считаю, что я должен использовать опережающее объявление однако я попытался следующие: -

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>(); 

который приводит к следующей ошибке: -

Error error C2027: use of undefined type 'foo::bar'

Любая помощь была бы признательна, спасибо!

+2

Он отлично работает с GCC и [Clang] (http://coliru.stacked-crooked.com/a/5244a59ca673d26c) дал опережающее объявление, что вы должны работать. –

+0

@ Daniel Frey Вы вызываете select() на baz? – chrisw

+0

Да, просто нажмите ссылку в моем комментарии. –

ответ

3

Error error C2027: use of undefined type 'foo::bar'

сообщение об ошибке, кажется, указывает, что пересылаемые объявлен вложенный тип bar в foo. Вам необходимо отправить декларацию правильного типа (переместите объявление bar на уровень пространства имен только по определению foo)

0

EDIT: Этот ответ неверен. bar не обязательно быть заполненным, если select - определено, оно должно быть заполнено, если select is экземпляр. Перемещение определения select вне очереди после спецификации класса для bar не требуется.


Проблема заключается в том, что ваше определение select внутри класса спецификатора для foo требует bar быть полным. Если вы перешлите объявление bar и только объявитеselect в спецификаторе класса, вы можете переместить определение select вне линии до конца bar. It then compiles fine:

#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)); 
} 
+0

Отличный ответ, но другой ответ решил это для меня, поскольку это был момент, который заставил меня осознать мою ошибку, как только он опубликовал. – chrisw

+1

@ chrisw69: Очень полезно научиться читать сообщения об ошибках, а затем читать * сообщения об ошибках :) –

Смежные вопросы