0

又一个模板问题!我正在尝试获取一个模板方法,如果它有运算符 << 的重载,它将输出一个对象。我几乎所有东西都在工作,并实现了一个 enable_if 以使 g++ 为每种类型的对象选择预期的专业化。

事情是,对于一个非重载的对象,它工作得很好。但是对于重载,我的两个专业都是 g++ 的合理选择,而不是编译它会输出一个模棱两可的重载错误。

这是代码:

template<typename T>
  static void   Print(Stream& out, T& param, typename enable_if<CanPrint<T>::value>::type = 0)
  {
    out << param;
  }

  template<typename T>
  static void   Print(Stream& out, T& param)
  {
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
  }

我明白为什么这样的事情是模棱两可的。然而我想不出一种让它更明显的方法......我如何让编译器明白只有在第一个重载不能选择时才选择第二个重载?

4

3 回答 3

8

您会感到模棱两可,因为在这两种情况下,您都有一个函数,它接受一个流,然后是您的类型T作为前两个参数。这虽然有效:

#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <typeinfo>

template <class T>
struct CanPrint { enum { value = 0 }; };

template <>
struct CanPrint<int> { enum { value = 1 }; };

template<typename T>
typename boost::enable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << param << std::endl;
}

template<typename T>
typename boost::disable_if<CanPrint<T>, void>::type 
    Print(std::ostream& out, T& param)
{
    out << "/!\\" << typeid(param).name() << " does not have any overload for <<.\n";
}

int main()
{
    int i = 1;
    double d = 2;

    Print(std::cout, i);
    Print(std::cout, d);
}
于 2011-06-18T09:15:19.740 回答
1

歧义是因为默认参数值。

调用Print(stream, whatever)可以解析为具有默认第三个参数的第一个版本或没有第三个参数的第二个版本。

去掉默认值,编译器就明白了。否则,它们都可以始终被选中。

于 2011-06-18T09:06:10.893 回答
1

我相信这与模板无关。以这种方式重载的自由函数会产生同样的模棱两可的错误。

检查这个简单的代码示例,它类似于您在模板示例中所做的事情:

void doSomething(int i, int j, int k );
void doSomething(int i, int j, int k = 10);


void doSomething(int i, int j, int k)
{

}

void doSomething(int i, int j)
{

}


int main()
{
    doSomething(10,20);
    return 0;
}

错误是:

prog.cpp:18: error: call of overloaded ‘doSomething(int, int)’ is ambiguous
prog.cpp:5: note: candidates are: void doSomething(int, int, int)
prog.cpp:10: note:                 void doSomething(int, int)

显然,您不能仅基于默认参数以这种方式重载函数。

于 2011-06-18T09:07:03.723 回答