Я работаю над проверкой правильности реализации URef в моих контейнерах-контейнерах. Единственный очевидный способ, который я могу придумать, — это попытаться выяснить способ обнаружения перемещения объекта.
Есть ли хороший способ проверки, чтобы убедиться, что объект не был скопирован? Или есть другой способ проверить то, что я хочу? Я бы предпочел решение, которое не требует изменения классов, которые я тестирую. Потому что их пара десятков.
Не могли бы вы предоставить больше информации о том, что у вас есть? Например, каков ваш контейнер, как вы его используете, можете ли вы изменить его или нет, и т. Д. Возможно, вы можете проверить это без изменения вашего контейнера, а с помощью специального типа элемента контейнера — который отслеживает копии и перемещения.
Несколько разных контейнеров и несколько отдельных шаблонных функций. В основном это обертки вокруг типов библиотек STL, таких как deque, list, map, set и т. Д.
Есть ли хороший способ проверки, чтобы убедиться, что объект не был скопирован?
Вы можете попробовать следующую проверку:
#include <boost/container/vector.hpp>
#include <iostream>
#include <ostream>
#include <vector>
#include <string>
using namespace boost;
using namespace std;
struct Test
{
bool copied;
Test()
: copied(false)
{
}
Test(const Test&)
: copied(true)
{
}
};
template<typename Container>
void check_move_constructor()
{
Container from(1);
Container to(boost::move(from));
cout << "\tmove constructor is" << (to[0].copied ? " not" : "") << " working" << endl;
}
template<typename Container>
void check_move_assignment()
{
Container from(1);
Container to;
to=boost::move(from);
cout << "\tmove assignment is" << (to[0].copied ? " not" : "") << " working" << endl;
}
template<typename Container>
void check_move(const string &name)
{
cout << name << " :" << endl;
check_move_constructor< Container >();
check_move_assignment< Container >();
cout << string(16,'_') << endl;
}
int main()
{
cout << boolalpha;
check_move< container::vector<Test> >("boost::container::vector");
check_move< vector<Test> >("std::vector");
return 0;
}
Выходы MSVC2008:
boost::container::vector :
move constructor is working
move assignment is working
________________
std::vector :
move constructor is not working
move assignment is not working
________________
Обратите внимание, что в этом коде я использовал явное перемещение из lvalues, поэтому Copy-elision здесь не может работать.
Постскриптум Другой способ сделать это — проверить сгенерированный ассемблерный код. Например, опция компилятора / FA в MSVC или -S в GCC.
Вы можете пометить достопримечательность с помощью вызова специальной функции:
__declspec(noinline) void asm_marker(int line) { volatile int i=line; };
#define ASM_MARKER asm_marker(__LINE__)
И поместите этот маркер в коде:
ASM_MARKER;
func_of_interest();
ASM_MARKER;
Asm-код может выглядеть так:
mov ecx, 235 ; 000000ebH
call ?asm_marker@@YAXH@Z ; asm_marker
mov edi, r12d
lea rcx, QWORD PTR [rdi+rdi*4]
mov rax, QWORD PTR vec$[rsp]
lea r9, QWORD PTR [rax+rcx*8]
mov rbx, QWORD PTR vec$[rsp+32]
mov ecx, 237 ; 000000edH
call ?asm_marker@@YAXH@Z ; asm_marker
Добавьте логическое поле, для которого установлено false
когда объект построен. В конструкторе перемещения и операторе присваивания перемещения назначьте true
в это поле в объекте, который перемещается из.