虽然定义了强制运算符,但没有强制转换

时间:2017-10-04 10:48:03

标签: c++ templates casting typecast-operator

有人可以帮我理解为什么以下代码无法编译:

template< typename T >
class A
{};

template< typename U >
class wrapper
{
  public:
    // cast operator
    operator wrapper< A<void> > ()
    {
      return wrapper< A<void> >{};
    }

};

template< typename T >
void foo( wrapper< A<T> > )
{}


int main()
{
  foo(  wrapper<void>{} );
}

错误消息:

t.cpp:24:7: error: no matching function for call to 'foo'
      foo(  wrapper<void>{} );
      ^~~
t.cpp:18:10: note: candidate template ignored: could not match 'A<type-parameter-0-0>' against 'void'
    void foo( wrapper< A<T> > )
         ^
1 error generated.

以及如何修复它?

我希望使用wrapper<void>的强制转换运算符将wrapper< A<void >投放到class wrapper

2 个答案:

答案 0 :(得分:3)

您可以使用wrapper< void >明确地将wrapper< A<void> >投射到static_cast来解决此问题,如下所示:

int main()
{
  foo( static_cast< wrapper< A<void> > >(wrapper<void>{}) );
}

顺利编译。

请注意,模板推导确实会尝试完全匹配模板参数而不进行转换。这意味着如果为了使事物完全匹配而需要强制转换,那么演员必须是明确的。

答案 1 :(得分:3)

问题是foo - s模板推断因为隐式转换而失败。

  • foo尝试推断出类型T
  • P = wrapper<void>,A = wrapper<A<T>>
  • foo无法推断出A<T>是什么

因此,我们必须帮助foo推断T.

解决方案1 ​​

foo明确知道什么是T:

foo<void>( wrapper<void>{} );

解决方案2

明确地将wrapper投放到wrapper< A<void> >,让foo知道T是什么:

foo( static_cast< wrapper< A<void> > >(wrapper<void>{}) );