Я задал ряд вопросов, относящихся к одному и тому же исходному коду в следующем порядке:
- экспериментируя с объединениями и битовыми полями в пределах a-структуры и шаблоны
- попытка перевернуть порядок битов в stdbitset
- избегание неоднозначности-in-overload-resolution
Я также задавал эти серии вопросов в Code Review, которые также имеют отношение.
- эмуляция виртуальных регистров путем экспериментирования с объединениями-битовыми полями-структурами-шаблонами-специализациями
- эмуляция виртуальных регистров-часть-2
Это должно дать вам краткий обзор моей оригинальной конструкции кода, и это там для справочной и справочной информации.С тех пор я начал смотреть на свой рабочий код и хотел еще больше упростить его.
Затем я решил удалить специализации шаблонов и сделать так, чтобы мой класс Register имел ширину 64 бита вместо 8 бит по умолчанию, а специализация более высокая.регистры размера заказа.
Я пытаюсь воплотить идею, что можно получить доступ к данным любым из следующих способов:
- Полная стоимость: - все 64-битное слово
- Половинное значение (я): - 2 отдельных 32-битных слова
- Квартальное значение (я) - 4 отдельных 16-битных слова
- Восьмое значение (я) - 8 отдельных 8-битных байтов
А благодаря использованию утилиты std::bitset
можно легко получить доступ к любому из битов в полном 64-битном регистре.С помощью объединений я должен быть в состоянии правильно отобразить память так, чтобы регистр мог быть представлен и доступен любой из следующих комбинаций:
std::bitset<64> qword
std::bitset<32> dword[2]
std::bitset<16> word[4]
std::bitset<8> byte[8]
Концепция использования объединения состоит в том, чтобы в памяти был один пробел, представляющий 64 бита для любого заданного регистра,Теперь я пытаюсь сохранить мой класс Register легко копируемым.
Поэтому я изменил исходный код из того, что можно найти по ссылкам выше, до более простой версии этого:
Register.h
#include <algorithm>
#include <bitset>
#include <string>
#include <vector>
namespace vpc {
typedef std::int8_t i8;
typedef std::int16_t i16;
typedef std::int32_t i32;
typedef std::int64_t i64;
const std::uint16_t BYTE = 0x08;
const std::uint16_t WORD = 0x10;
const std::uint16_t DWORD = 0x20;
const std::uint16_t QWORD = 0x40;
typedef std::bitset<BYTE> Byte;
typedef std::bitset<WORD> Word;
typedef std::bitset<DWORD> DWord;
typedef std::bitset<QWORD> QWord;
union Bits {
QWord value;
DWord dword[2];
Word word[4];
Byte byte[8];
};
struct Register {
Bits bits;
Register() = default;
};
} // namespace vpc
Затем я хочу проверить, чтобы убедиться, что все до сих пор легко копируется.Итак, я запускаю эту короткую программу.
main.cpp
#include <iostream>
#include <type_traits>
#include "Register.h"
int main() {
using namespace vpc;
std::cout << std::boolalpha;
std::cout << "std::bitset<64> is trivially copyable "
<< std::is_trivially_copyable<std::bitset<64>>::value << '\n'
<< "QWord is trivially copyable "
<< std::is_trivially_copyable<QWord>::value << '\n'
<< "DWord is trivially copyable "
<< std::is_trivially_copyable<DWord>::value << '\n'
<< "Word is trivially copyable "
<< std::is_trivially_copyable<Word>::value << '\n'
<< "Byte is trivially copyable "
<< std::is_trivially_copyable<Byte>::value << '\n'
<< "Bits is trivially copyable "
<< std::is_trivially_copyable<Bits>::value << '\n'
<< "Register is trivially copyable "
<< std::is_trivially_copyable<Register>::value << '\n';
return EXIT_SUCCESS;
}
И я получаю этот вывод:
std::bitset<64> is trivially copyable true
QWord is trivially copyable true
DWord is trivially copyable true
Word is trivially copyable true
Byte is trivially copyable true
Bits is trivially copyable true
My Register is trivially copyable true
Теперь, глядя наобъединение Биты это заявляет, что это легко копируемое.Таким образом, вместо объявления переменной типа Bits в структуре в качестве члена данных;Я считаю, что мы должны иметь возможность иметь анонимный союз в нашей структуре, чтобы мы могли получить право на наши слова, слова, слова и байты напрямую.Итак, теперь класс будет выглядеть так:
struct Register {
union {
QWord value;
DWord dword[2];
Word word[4];
Byte byte[8];
};
Register() = default;
};
Затем я запускаю эту строку кода в нашем main.cpp
// code...
std::cout << std::boolalpha;
std::cout << "Register is trivially copyable "
<< std::is_trivially_copyable<Register>::value << '\n';
// code...
И я получаю такой вывод:
Register is trivially copyable true
Хорошо, пока все хорошо.
Сейчас я работаю над своей функцией, которая работает с объектом Register.Это обратит порядок битов, как видно из ранее заданных вопросов.За исключением этого случая я не использую шаблоны.Итак, здесь я объявляю прототип функции в Register.h
после моего класса:
Register reverseBitOrder( Register& reg, bool copy = false );
И затем я создал файл Register.cpp
только для реализации этой функции.
Register.cpp
#include "Register.h"
namespace vpc {
Register reverseBitOrder(Register& reg, bool copy) {
auto str = reg.value.to_string();
std::reverse(str.begin(), str.end());
if (copy) { // return a copy
Register cpy;
cpy.value = QWord(str);
return cpy;
} else {
reg.bits.value = QWord(str);
return { 0 };
}
}
} // namespace vpc
Теперь, когда у меня написана функция, я очищаю свое решение и пытаюсь скомпилировать «Register.h».Тем не мение;Я получаю эту ошибку компилятора для Visual Studio 2017 с настройкой языка, установленной на последний черновой стандарт или флагом (/std:c++latest)
.
--- Build started: Project: Corgi64, Configuration: Debug Win32 ------
1>Register.cpp
1>c:\***\register.cpp(10): error C2280: 'vpc::Register::Register(void)': attempting to reference a deleted function
1>c:\***\register.h(40): note: see declaration of 'vpc::Register::Register'
1>c:\***\register.h(40): note: 'vpc::Register::Register(void)': function was implicitly deleted because 'vpc::Register' has a variant data member 'vpc::Register::value' with a non-trivial default constructor
1>c:\***\register.h(34): note: see declaration of 'vpc::Register::value'
1>Done building project "Corgi64.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Так что, когда я нажимаю на ошибку C2280, она направляет меня к объявлению моегоРегистровая переменная cpy
.Когда я перемещаю курсор мыши поверх переменной cpy
, она выдает мне сообщение:
vpc :: Register cpy
На конструктор по умолчанию "vpc :: Register" нельзя ссылаться -- это удаленная функция
Таким образом, мой вопрос звучит так: почему конструктор по умолчанию удаляется, если все ранее было тривиально копируемым? Поскольку я теперь использую его внутри функции, внезапно я заявляю, что в моей структуре есть инвариантный член, который не имеет тривиально копируемого конструктора, и он указывает на Register::value
как на виновника. Что вызывает это, как и почему? Что я могу сделать, чтобы это исправить или решить?