模板专业化是不明确的

Template specializations are ambiguous

本文关键字:不明确 专业化      更新时间:2023-10-16

还有一个模板问题!我正在尝试获得一个模板方法,如果它有运算符<lt;。我几乎所有的东西都在工作,并实现了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";
  }

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

您会得到歧义,因为在这两种情况下,您都有一个函数,它将一个后面跟着类型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);
}

模糊性是因为默认参数值。

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

删除默认值,编译器就会理解。否则,他们两个总是可以选择的。

我认为这与模板无关。以这种方式重载的自由函数也会出现同样严重的错误。

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

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)

很明显,不能仅基于默认参数以这种方式重载函数