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

时间:2011-03-28 16:02:31

标签: c++

我有一个A类:

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

和类B.我希望类型B的对象在作为函数参数给出时隐式转换为A. B看起来像这样:

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

然而,我的测试(下面)因GCC 4.5而失败,给出错误:没有匹配函数来调用'test(B&amp;)'我在哪里错了?其他编译器也拒绝这个吗?

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;
}

P.S。我现在把自己的解决方案放在下面的答案中。

6 个答案:

答案 0 :(得分:3)

与您的问题无关,但return *new A<T,0>();错误,因为泄漏内存会导致内存泄漏。你应该在这里使用newreturn A<T, 0>();并从返回类型中删除引用可以正常工作并且不会泄漏内存。

答案 1 :(得分:2)

如果您想要从B到A的隐式转换,您需要:

B上的演员:

operator A<T,0>();

或带有B引用的A构造函数:

A( const B& other );

或者B来自A.你声明的内容:

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

看起来有点像一个错误声明的重载地址。

但是,由于test()接受引用(并且非const),因此转换操作符选项将不起作用。

这是我测试过的:

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;
}

通过初始化局部变量转换为A可以正常工作。

答案 2 :(得分:1)

你确定你真的想要这样的隐式转换吗?这听起来像是混淆自己或其他维护者的完美方式,或者更糟糕的是,使用错误的参数调用函数,因为隐式转换允许它。相反,请考虑make_A std::make_pair模板,以明确显示您在呼叫站点的意图。

答案 3 :(得分:1)

如下所示提供test的重载将允许写入 问题test(b) 例如:

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

test(b); // caller

如果不允许这样的重载但允许您修改B 定义,如何提供返回A的成员函数 如下所示,而不是转换功能?

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

test( b.to_A() );

如果您不允许修改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 ) );

希望这有帮助

答案 4 :(得分:0)

这在VC ++中也失败了。要使其工作,请添加以下方法:

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

这将采用实际的B,明确地进行转换(通过static_cast),然后使用我们刚刚制作的test来调用A

我运行时遇到错误。我希望这只是示例代码,而您在实际代码中没有delete &a。 RobH为您提供了一个更好的转换运算符,并避免指针混乱。

答案 5 :(得分:0)

我已经决定使用Konrad建议的pass by value转换运算符; Let_Me_Be的显式模板函数调用;我在顶部撒了一点C ++ 0x魔法:一个关于要测试的参数的右值参考。 (或者,现在应该是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;
}