被忽略的框架模板:无法推断模板参数

问题描述 投票:0回答:2

现在我有2类A和B:

class A {
};

class B : public A {
};

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

Ref<B> t;
Ref<A> t2(t);

这实际上应该编译,但是我得到了最后2个构造函数(使用可转换类型的构造函数)提到的错误(clang),这实际上应该为该分配启动。需要做些什么才能在这里进行模板参数扣除工作?

	
您正在错误地使用

std::enable_if
c++ templates c++11
2个回答
10
投票
,这应该为

12

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

ther,第二个模板参数被默认为如果不转换为T2*the,这将是您想要的:

如果是

T1*

,那么这等同于:

std::is_convertible<T2*, T*>::value

  • ,否则,您会得到:
    
    
    
    true
  • 在您的原始代码中,当成功的模板成功时,您的模板等同于:
template<typename T2, typename = void> // Ok, well-formed
Ref(Ref<T2> const& value);
    这不是您想要的(在这种情况下,编译器无法推断出这两个)。
1
如果您可以访问C ++14.

,则可以用

template<typename T2, typename = /* Something ill-formed */>
Ref(Ref<T2> const& value);
代替std::enable_if

2

这是一种可能性,另一个是使用
template<typename T2, typename T2> // Well-formed, but T2 cannot be deduced Ref(Ref<T2> const& value);

(或类似的东西),但我更喜欢
T2

版的版本。在一般情况下,它们并不是严格等同的,但是在这种确切的情况下,它们并不重要。

@Holt的答案很好,正确地说明了如何使用
typename std::enable_if<>::type
在任何情况下,在这种情况下,您根本不需要使用它。 这里足够了,错误消息对此会更好:

std::enable_if_t<>

std::enable_if_t<..., int> = 0

会给您这样的错误:
  Error:静态断言失败:!
  static_assert(std :: is_convertible :: value,“!”);

sfinae表达式通常用于(我说)

4
投票
。 如果您没有一组有效的替代方案可以从中取出正确的替代方案,通常是优选的。

要完成霍尔特的答案,请注意,您可以通过

typename = ...
将默认构造函数和构造函数合并为

std::enable_if


static_assert
等于

template<typename U> Ref(Ref<U> const& value) { static_assert(std::is_convertible<U, T>::value, "!"); // whatever you want } template<typename U> Ref(Ref<U> &&value) { static_assert(std::is_convertible<U, T>::value, "!"); // whatever you want }
C

。 您的摘要错过了。使用

拷贝和交换成语,您可以使用它来对测试进行分解
A

Ref<A> t3(Ref<C>{});
    

© www.soinside.com 2019 - 2024. All rights reserved.