Ambiguous overload for 'operator<<' with template template arguments
I'm trying to make a template class where one would be able to define the (STL) container used by the class as a template parameter. So I did the following:
template <typename T = float,
template < class, class > class Container = std::vector,
class Alloc = typename std::vector < Spectrum < T > >::allocator_type>
class Spectrogram;
My problem is that when I define my overload for the stream operator as
// 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;
}
and then create some test code as
Spectrogram < float > spectrogram;
// Fill the spectrogram etc. -- codepart omitted
std::cout << spectrogram;
I get the following error:
Ambiguous overload for 'operator<<'
I'm probably doing something wrong, but I just can't figure it out.
Thanks for any help, Ádám
P.S. The referenced classes have the following definitions:
// 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;
};
I'm using GCC 4.2 with XCode 4.0.2.
Although it seems the problem is solved by a compiler upgrade or minor syntactic adjustment, you might want to simplify the parameterization.
class Spectrogram
only really depends on the class used to contain its data. So this would work with no loss of functionality:
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;
};
This eliminates the cascading sequence of default arguments, but greatly simplifies the design. You can again simplify usage by providing typedef
s and (if you're really using a variety of parameterizations) metafunctions that map the desired parameters to the required Container
.
typedef Spectrum< vector< float > > Spectrum_sp; // single-precision
typedef Spectrograph< Spectrum_sp > Spectrograph_sp;
Compiles under GCC 4.3 and 4.4, but 4.1 gives an error similar to what you describe. Must be a GCC bug.
精彩评论