Неоднозначная перегрузка для оператора «оператор <<» с аргументами шаблона - PullRequest
5 голосов
/ 09 августа 2011

Я пытаюсь создать шаблонный класс, в котором можно было бы определить контейнер (STL), используемый классом в качестве параметра шаблона.Поэтому я сделал следующее:

template <typename T = float,
          template < class, class > class Container = std::vector,
          class Alloc = typename std::vector < Spectrum < T > >::allocator_type>
class Spectrogram;

Моя проблема в том, что когда я определяю свою перегрузку для оператора потока как

// Definition inside the 'public' part of the 'Spectrogram' class
template <typename Type,
          template < class, class > class C,
          class A>
friend std::ostream & operator << ( std::ostream &, const Spectrogram < Type, C, A > & );

// Implementation
template <typename Type,
          template < class, class > class C,
          class A>
std::ostream & operator << ( std::ostream & o, const Spectrogram < Type, C, A > & s )
{
   // Transparent implementation
   return o;
}

, а затем создаю некоторый тестовый код как

Spectrogram < float > spectrogram;
// Fill the spectrogram etc. -- codepart omitted
std::cout << spectrogram;

Я получаю следующую ошибку:

Ambiguous overload for 'operator<<'

Возможно, я что-то не так делаю, но не могу понять.

Спасибо за любую помощь, Адам

PS Указанные классы имеют следующие определения:

// Spectrum
template < typename T = float, class Container = std::vector < T > > class Spectrum {
public:
   typedef T ( * WindowFunction ) ( const T & );
   typename Container::const_iterator begin ( void ) const;
   typename Container::const_iterator end ( void ) const;
   typename Container::const_reverse_iterator rbegin ( void ) const;
   typename Container::const_reverse_iterator rend ( void ) const;
   WindowFunction getWindowFunction ( void ) const;
   typename Container::size_type getWindowSize ( void ) const;
   typename Container::size_type getFFTSize ( void ) const;
   void setWindowFunction ( const WindowFunction & );
   void setFFTSize ( const typename Container::size_type & );
   template < class InputIterator > void import ( const InputIterator &, const InputIterator & );
   template < typename Type, class C > friend std::ostream & operator << ( std::ostream &, const Spectrum < Type, C > & );
protected:
   WindowFunction windowFunction;
   typename Container::size_type windowSize;
   Container spectrum;
   void clear ( void );
};

// Spectrogram
template < typename T = float, template < class, class > class Container = std::vector, class Alloc = typename std::vector < Spectrum < T > >::allocator_type > class Spectrogram {
public:
   typedef typename Container < Spectrum < T >, Alloc >::const_iterator Iterator;
   typedef typename Container < Spectrum < T >, Alloc >::const_reverse_iterator ReverseIterator;
   typedef typename Container < Spectrum < T >, Alloc >::size_type size_type;
   Iterator begin ( void ) const;
   Iterator end ( void ) const;
   ReverseIterator rbegin ( void ) const;
   ReverseIterator rend ( void ) const;
   size_type size ( void ) const;
   bool empty ( void ) const;
   WindowTypes getWindowType ( void ) const;
   double getHopFactor ( void ) const;
   unsigned long getWindowSize ( void ) const;
   unsigned short getOversamplingFactor ( void ) const;
   unsigned long getHopSize ( void ) const;
   void setWindowType ( const WindowTypes & );
   void setHopFactor ( const double & );
   void setWindowSize ( const unsigned long & );
   void setOversamplingFactor ( const unsigned short & );
   template < class InputIterator > void import ( const InputIterator &, const InputIterator & );
   template < typename Type, template < class, class > class C, class A > friend std::ostream & operator << ( std::ostream &, const Spectrogram < Type, C, A > & );
protected:
   Container < Spectrum < T >, Alloc > spectrogram;
   double hopFactor;
   unsigned long windowSize;
   unsigned short oversamplingFactor;
   WindowTypes windowType;
};

Я использую GCC 4.2 с XCode 4.0.2.

Ответы [ 2 ]

2 голосов
/ 09 августа 2011

Хотя кажется, что проблема решается путем обновления компилятора или незначительной синтаксической настройки, вы можете упростить параметризацию.

class Spectrogram действительно зависит только от класса, используемого для хранения его данных.Так что это будет работать без потери функциональности:

template< typename Container >
class Spectrum {
public:
    typedef typename Container::value_type value_type;
    ...
};

template< typename Container >
class Spectrogram {
    // assume Container::value_type is a specialization of Spectrum
    typedef typename Container::value_type::value_type numeric_type;
};

Это исключает каскадную последовательность аргументов по умолчанию, но значительно упрощает дизайн.Вы можете снова упростить использование, предоставив typedef s и (если вы действительно используете различные параметризации) метафункции, которые отображают нужные параметры в требуемые Container.

typedef Spectrum< vector< float > > Spectrum_sp; // single-precision
typedef Spectrograph< Spectrum_sp > Spectrograph_sp;
1 голос
/ 16 августа 2011

Компилируется в GCC 4.3 и 4.4, но 4.1 выдает ошибку, аналогичную описанной вами. Должна быть ошибка GCC.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...