候选模板被忽略:无法推断模板参数

Mik*_*hke 3 c++ templates c++11

第一:错误信息确实如此给出.在"论证"这个词后面只有引号,这本身就很奇怪.但这是我试图解决的问题.我正在编写一个内部存储(模板)类型引用的类,并且还应该接受可转换类型:

template<typename T>
class Ref {
public:
    Ref();
    Ref(std::nullptr_t);
    explicit Ref(T *value);

    Ref(Ref const& value);

    template<typename T2, typename std::enable_if<std::is_convertible<T2*, T*>::value, T2>::type>
    Ref(Ref<T2> const& value);

    template<typename T2, typename std::enable_if<std::is_convertible<T2*, T*>::value, T2>::type>
    Ref(Ref<T2> &&value);
private:
  T *_value;
};
Run Code Online (Sandbox Code Playgroud)

现在我有2个A和B类:

class A {
};

class B : public A {
};
Run Code Online (Sandbox Code Playgroud)

我正在尝试将B的Ref实例分配给A类的Ref变量:

Ref<B> t;
Ref<A> t2(t);
Run Code Online (Sandbox Code Playgroud)

这实际上应该编译,但我得到了最后2个构造函数(那些采用可转换类型)的上述错误(clang),这实际上应该为该赋值启动.需要做些什么来使模板参数推导在这里工作?

Hol*_*olt 8

你使用std::enable_if不当,这应该是1 2:

template<typename T2,
         typename = 
             typename std::enable_if<std::is_convertible<T2*, T*>::value>::type>
Ref(Ref<T2> const& value);
Run Code Online (Sandbox Code Playgroud)

这里,第二个模板参数默认T2*为无法转换为失败的东西T1*,这就是你想要的:

  • 如果std::is_convertible<T2*, T*>::valuetrue,则相当于:
template<typename T2, typename = void> // Ok, well-formed
Ref(Ref<T2> const& value);
Run Code Online (Sandbox Code Playgroud)
  • 否则,你得到:
template<typename T2, typename = /* Something ill-formed */>
Ref(Ref<T2> const& value);
Run Code Online (Sandbox Code Playgroud)

在原始代码中,当std::enable_if成功时,您的模板相当于:

template<typename T2, typename T2> // Well-formed, but T2 cannot be deduced
Ref(Ref<T2> const& value);
Run Code Online (Sandbox Code Playgroud)

这不是你想要的(编译器T2在这种情况下无法推断出两者).

1如果您有权访问C++ 14 typename std::enable_if<>::type,std::enable_if_t<>则可以替换.

2这是一种可能性,另一种是使用std::enable_if_t<..., int> = 0(或类似的东西),但我更喜欢使用的版本typename = ....它们在一般情况下并不完全相同,但在这种精确的情况下它并不重要.