为什么我的功能跳过试图解决的不兼容的模板功能,默认为解决正规函数? [重复](Why doesn

2019-09-21 04:44发布

这个问题已经在这里有一个答案:

  • 为什么不能将模板函数解析一个指向派生类是指向基类 1回答
std::string nonSpecStr = "non specialized func";
std::string const nonTemplateStr = "non template func";

class Base {};
class Derived : public Base {};

template <typename T> std::string func(T * i_obj)
{ 
   ( * i_obj) += 1;
   return nonSpecStr; 
}

std::string func(Base * i_obj) { return nonTemplateStr; }

void run()
{
   // Function resolution order
   // 1. non-template functions
   // 2. specialized template functions
   // 3. template functions
   Base * base = new Base;
   assert(nonTemplateStr == func(base));

   Base * derived = new Derived;
   assert(nonTemplateStr == func(derived));

   Derived * derivedD = new Derived;

   // When the template function is commented out, this
   // resolves to the regular function. But when the template
   // function is uncommented, this fails to compile because
   // Derived does not support the increment operator. Since
   // it doesn't match the template function, why doesn't it
   // default to using the regular function?
   assert(nonSpecStr == func(derivedD));
}

Answer 1:

模板参数推导,使您的模板函数的精确匹配与推导TDerived 。 重载决策只着眼于功能的签名,并在身体不看的。 它会如何处理其他工作来声明函数,调用它的一些代码,后来界定呢?

如果你真的想检查一个类型的操作的这种行为,你可以用SFINAE这样做:

// C++11
template<class T>
auto f(T* p)
    -> decltype((*p)+=1, void())
{
  // ...
}

这将使如果置换失败T不支持operator+=



Answer 2:

T型可以是不需要摆在首位的隐式转换的精确匹配,所以最好是你的基类形式中,非模板函数。

您可以专注模板功能不符合的隐性契约,并已如果你发现这个问题它调用非模板函数,而不是一个类型。 同样,你可以提供非模板版本匹配你会用这么不需要的隐式转换的确切派生类。 这两个选项不只是没有使用运营商虽然更痛苦。 代码你的模板,以便它们隐含的模板合同要求尽可能少的:)



文章来源: Why doesn't my function skip trying to resolve to the incompatible template function, and default to resolving to the regular function? [duplicate]