简体   繁体   English

隐式转换为C ++模板对象

[英]Implicit conversion to a C++ template object

I have a class A: 我有一个A类:

template <typename T, int I> struct A {};

and a class B. I would like object's of type B to implicitly convert to A when given as function arguments. 和B类。我希望类型B的对象在作为函数参数给出时隐式转换为A. B looks like this: B看起来像这样:

template <typename T>
struct B {
  operator A<T,0> &() const { return *new A<T,0>(); }
};

However, my test (below) fails with GCC 4.5, giving the error: no matching function for call to 'test(B&)' Where am I going wrong here? 但是,我的测试(下面)失败了GCC 4.5,给出错误: 没有匹配函数来调用'test(B&)'我在哪里错了? Do other compilers also reject this? 其他编译器也拒绝这个吗?

template <typename T, int I>
void test(A<T,I> &a) { delete &a; }

int main(int argc, char *argv[])
{
  B<int> b;
  test(b);
  return 0;
}

ps I've now put my own solution in an answer below. ps我现在把自己的解决方案放在下面的答案中。

Unrelated to your problem but return *new A<T,0>(); 与您的问题无关但return *new A<T,0>(); is wrong since it 这是错的 leaks memory 泄漏记忆 invites a memory leak. 引发内存泄漏。 You should not use new here. 应该使用new位置。 return A<T, 0>(); and removing the reference from the return type works just fine and does not leak memory. 并从返回类型中删除引用工作正常,并不会泄漏内存。

If you want an implicit conversion from B to A you would need either: 如果您想要从B到A的隐式转换,您需要:

A cast operator on B: B上的演员:

operator A<T,0>();

or an A constructor which takes a B reference: 或者是一个采用B引用的构造函数:

A( const B& other );

or for B to derive from A. What you have declared: 或者B来自A.你宣称:

operator A<T,0> &() const;

looks a bit like an ill-declared address-of overload. 看起来有点像一个错误声明的重载地址。

However, since test() takes a reference (and non-const at that), the casting operator option won't work. 但是,由于test()接受引用(并且非const),因此转换操作符选项将不起作用。

This is what I've tested: 这是我测试过的:

template <typename T, int I> struct A {};

template <typename T>
struct B {
  //operator A<T,0> &() const { return *new A<T,0>(); }

    template< int I >
    operator A<T, I> () const { return A< T, 0 >(); }
};

template <typename T, int I>
void test(A<T,I> &) { }

int f()
{
  B<int> b;

  A<int, 0> a( b );
  test(a); // <-- Success

  test(b); // <-- Failure, "could not deduce template argument"
  return 0;
}

Conversion to A by initialising a local variable works fine. 通过初始化局部变量转换为A工作正常。

Are you sure you actually want such an implicit conversion here? 你确定你真的想要这样的隐式转换吗? It sounds like a perfect way to confuse yourself or another maintainer, or worse, call a function using the wrong argument because the implicit conversion allows it. 这听起来像是混淆自己或其他维护者的完美方式,或者更糟糕的是,使用错误的参数调用函数,因为隐式转换允许它。 Instead, consider a make_A template like std::make_pair to explicitly show your intention at the call site. 相反,请考虑像std::make_pair这样的make_A模板,以明确显示您在呼叫站点的意图。

Providing an overload of test like the following will enable to write test(b) as in the question. 提供如下所述的test过载将使得能够在问题中编写test(b)
For example: 例如:

template <typename T>
void test(B<T> const &b) {
  test( static_cast< A<T,0>& >( b ) );
}

test(b); // caller

If such overload isn't allowed but you are allowed to modify B 's definition, how about providing member function which returns A like the following, instead of conversion function? 如果不允许这样的重载但你可以修改B的定义,那么如何提供返回A成员函数,而不是转换函数?

template <typename T>
struct B {
  A<T,0> &to_A() const { return *new A<T,0>(); }
};

test( b.to_A() );

If you aren't allowed to modify B 's definition, the above to_A will be a free function like the following instead of member function: 如果不允许修改B的定义,上面的to_A将是一个自由函数,如下所示而不是成员函数:

template <typename T>
A<T,0> &to_A(B<T> const &b) {
  return static_cast< A<T,0>& >( b );
}

test( to_A( b ) );

Hope this helps 希望这可以帮助

This fails in VC++ too. 这在VC ++中也失败了。 To make it work, add this method: 要使其工作,请添加以下方法:

template <typename T>
void test(B<T> &b)
{
   test( static_cast< A<T,0>& > (b) );
}

This will take an actual B , explicitly do the conversion (via static_cast ), and then call test using the A we just made. 这将采用实际的B ,明确地进行转换(通过static_cast ),然后使用我们刚刚创建的A调用test

I get errors when I run it though. 我运行时遇到错误。 I hope this is just example code, and you're not doing delete &a in your actual code. 我希望这只是示例代码,而您在实际代码中没有delete &a RobH gave a better conversion operator for you, and avoids the pointer messiness. RobH为您提供了更好的转换运算符,并避免指针混乱。

I've settled on using the pass by value conversion operator suggested by Konrad; 我已经决定使用Konrad建议的pass by value转换运算符; the explicit template function call of Let_Me_Be; Let_Me_Be的显式模板函数调用; and I sprinkled a little bit of C++0x magic on top: an rvalue reference on the parameter to test. 我在顶部撒了一点C ++ 0x魔法:一个关于要测试的参数的右值参考。 (Or, should that be C++ 2011 now?) (或者,现在应该是C ++ 2011吗?)

template <typename T, int I> struct A { int x; };

template <typename T>
struct B {
  operator A<T,0> () const { return A<T,0>(); }
};

template <typename T, int I>
void test(A<T,I> &&a) { a.x=7; printf("%d\n", x); }

int main(int argc, char *argv[])
{
  B<int> b;
  test<int,0>(b);
  return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM