По причинам стирания типа у меня есть шаблон A<T>
, который может содержать любой тип данных. Когда A
имеет полиморфный тип Derived
, который является производным от Base
и я бросил его в A<Base>
, неопределенное поведение ССЗ дезинфицирующее сообщения об ошибках во время выполнения:неопределенное поведение при шаблоне литья, имеющем полиморфный тип
#include <iostream>
struct I
{
virtual ~I() = default;
};
template<typename T>
struct A : public I
{
explicit A(T&& value) : value(std::move(value)) {}
T& get() { return value; }
private:
T value;
};
struct Base
{
virtual ~Base() = default;
virtual void fun()
{
std::cout << "Derived" << std::endl;
}
};
struct Derived : Base
{
void fun() override
{
std::cout << "Derived" << std::endl;
}
};
int main()
{
I* a_holding_derived = new A<Derived>(Derived());
A<Base>* a_base = static_cast<A<Base>*>(a_holding_derived);
Base& b = a_base->get();
b.fun();
return 0;
}
компилировать & кнопкуВыполнения
$ g++ -fsanitize=undefined -g -std=c++11 -O0 -fno-omit-frame-pointer && ./a.out
выход:
main.cpp:37:62: runtime error: downcast of address 0x000001902c20 which does not point to an object of type 'A'
0x000001902c20: note: object is of type 'A<Derived>'
00 00 00 00 20 1e 40 00 00 00 00 00 40 1e 40 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'A<Derived>'
#0 0x400e96 in main /tmp/1450529422.93451/main.cpp:37
#1 0x7f35cb1a176c in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x400be8 (/tmp/1450529422.93451/a.out+0x400be8)
main.cpp:38:27: runtime error: member call on address 0x000001902c20 which does not point to an object of type 'A'
0x000001902c20: note: object is of type 'A<Derived>'
00 00 00 00 20 1e 40 00 00 00 00 00 40 1e 40 00 00 00 00 00 00 00 00 00 00 00 00 00 21 00 00 00
^~~~~~~~~~~~~~~~~~~~~~~
vptr for 'A<Derived>'
#0 0x400f5b in main /tmp/1450529422.93451/main.cpp:38
#1 0x7f35cb1a176c in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2176c)
#2 0x400be8 (/tmp/1450529422.93451/a.out+0x400be8)
Derived
У меня есть два вопроса:
- выводится дезинфицирующее Правильна?
- Если да, то как будет действующее преобразование от
A<Derived>
доA<Base>
?
Статический приведение от 'I *' к 'X' имеет неопределенное поведение, поскольку он фактически указывает на подобъект' Y', а 'X' и' Y' - разные типы (соответственно 'A ' и 'A '). –
Это не то, что люди обычно называют «стиранием типа». У стирания типа будет один (не шаблонный) тип 'A', который вы могли бы * построить * из произвольных типов. Полиморфизм будет в частных частях. Примерами стирания типа в стандартной библиотеке являются 'std :: function' и' std :: experimental :: any'. –
@KerrekSB У меня есть другой тип, который обертывается вокруг 'A'; Я не показывал его здесь, чтобы привести пример в соответствие с минимальным. –