使用不同的模板参数强制转换模板对象,这怎么可能

Cast a template object with different template parameters, how is this possible?

本文关键字:转换 对象 怎么可能 参数      更新时间:2023-10-16

今天我尝试了一些东西,认为它不起作用,但它确实有效,我不明白为什么......

我有一个类型 base 的对象,它不包含任何内容。
另一个类型derived继承自base,存储一个函数指针并调用它。
derived是一个模板对象,其参数是存储的函数等待的参数的类型。

如果我从 derived<void> 类型的对象中引用 base 类型并尝试将其转换为 derived<int> ...它确实有效。
你如何解释它,因为derived<>derived< int >是两种不同的类型?

一个简单的例子:

#include <iostream>
void foo( int ) { ::std::cout << "void foo( int )n"; }
void foo() { ::std::cout << "void foo()n"; }
struct base
{
  base() { ::std::cout << "tcreate basen"; }
  base( const base & ) { ::std::cout << "tcopy basen"; }
  base( base && ) { ::std::cout << "tmove basen"; }
  void operator =( const base & ) { ::std::cout << "tcopy assignment basen"; }
  void operator =( base && ) { ::std::cout << "tmove assignment basen"; }
};
template < typename ... Args >
struct derived : public base
{
  derived() { ::std::cout << "tcreate derivedn"; }
  derived( const derived & ) { ::std::cout << "tcopy derivedn"; }
  derived( derived && ) { ::std::cout << "tmove derivedn"; }
    derived & operator =( const derived & ) { ::std::cout << "tcopy assignment derivedn"; }
  derived & operator =( derived && ) { ::std::cout << "tmove assignment derivedn"; }
  void operator ()( Args ... args )
  {
    f( args ... );
  }
  void ( *f )( Args ... );
};

int main()
{
  derived<> derived_void;
  derived_void.f = ( void ( * )() )&foo;
  base & base_void = derived_void;
  derived<> &test = derived_void;
  static_cast< derived< int > & >( base_void )( 1 ); // compiles, makes no copy
//  static_cast< derived< int > & >( test )( 1 ); // doesn't compile
}

您可以在此处进行测试。

感谢您的帮助。

忘记模板。

你有一个类A,一个派生自A的类B,以及一个派生自A的类C

如果你有一个类型 A 的不言重值,你可以将其强制转换为 B &C & 。编译器通常无法知道具体的派生类型是什么,因此它相信您知道自己在做什么。

这正是你正在

做的事情:你正在AB &。您的A实际上是一个C对象,但编译器不知道这一点。

考虑一下:

struct X {};
struct A : X {};
struct B : X {};
X & x = get_object_ref(); //can return A& or B&, how would I know?
A & a = static_cast<A&>(x); //this will compile!
B & b = static_cast<B&>(x); //this will compile too!

如果static_cast<A&>(x)应该给出误差,那么static_cast<B&>(x)也应该通过对称给出误差。既然一个必须编译,那么两者都必须编译。

底线:base&总是可以向下转换为derive& - 它是一种语言功能。您有责任投向正确的derive&.