【问题标题】:Ambiguous overload for 'operator<<' with template template arguments带有模板模板参数的“运算符<<”的模棱两可的重载
【发布时间】:2011-08-09 09:55:02
【问题描述】:

我正在尝试创建一个模板类,其中可以将类使用的(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<<'

我可能做错了什么,但我就是想不通。

感谢您的帮助, 阿达姆

附:引用的类具有以下定义:

// 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。

【问题讨论】:

  • 不知道为什么这个问题被否决了。即使我不知道答案,这似乎也是一个合理的问题。
  • 我没有投反对票,这是一个很好的问题——但在我的大脑放弃它之前,我确实完成了这个问题的一半......虽然这更多地与 c++ 模板语法有关,而不是问题:)
  • 应该有大量重复的模板朋友可能是一样的。 - 模板模板参数也可能使其更复杂:为什么不是单个 Container 参数?您可以从中获取value_type
  • 您的代码在 GCC 4.6.1 下编译得很好。此外,您可以考虑将朋友设为非模板并将其定义为内联。
  • 在 GCC 4.3 和 4.4 下编译,但 4.1 给出了与您描述的类似的错误。必须是 GCC 错误。

标签: c++ templates operator-overloading


【解决方案1】:

虽然问题似乎已通过编译器升级或较小的语法调整得到解决,但您可能希望简化参数化。

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;
};

这消除了默认参数的级联顺序,但大大简化了设计。您可以通过提供typedefs 和(如果您真的使用各种参数化)将所需参数映射到所需的Container 的元函数再次简化使用。

typedef Spectrum< vector< float > > Spectrum_sp; // single-precision
typedef Spectrograph< Spectrum_sp > Spectrograph_sp;

【讨论】:

    【解决方案2】:

    在 GCC 4.3 和 4.4 下编译,但 4.1 给出了与您描述的类似的错误。一定是 GCC 错误。

    【讨论】:

      猜你喜欢
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      • 2011-12-19
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      相关资源
      最近更新 更多