Reputation: 7905
Here is my code:
Register.h
#include <assert.h>
#include <bitset>
#include <cstdint>
#include <iostream>
#include <iomanip>
#include <iterator>
#include <limits>
#include <numeric>
namespace vpc {
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
template<typename T>
struct Register {
T data;
T value;
std::bitset<sizeof(T)* CHAR_BIT> bits;
Register() = default;
template<typename P>
explicit Register(const P val) :
data{ static_cast<T>(val) },
value{ data },
bits{ data }
{}
template<typename P>
Register(const P val, const u8 idx) :
data{ static_cast<T>((val >> std::size(bits) * idx) &
std::numeric_limits<std::make_unsigned<T>>::max()) },
value{ data },
bits{ data }
{
assert(idx >= '\0' && idx < sizeof(T));
}
template<typename P>
Register(const Register<P>& reg) :
data{ static_cast<T>(reg.data) },
value{ data },
bits{ data }
{}
template<typename P>
Register(const Register<P>& reg, const u8 idx) :
data{ static_cast<T>((reg.data >> std::size(bits) * idx) &
std::numeric_limits<std::make_unsigned<T>>::max()) },
value{ data },
bits{ data }
{
assert(idx >= 0 && idx < sizeof(T));
}
};
template<typename T>
std::ostream& operator<<(std::ostream& os, const Register<T>& r) {
return os << "Reg" << std::size(r.bits) << '(' << +r.data << ")\nhex: 0x"
<< std::uppercase << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex
<< +r.data << std::dec << "\nbin: "
<< r.bits << "\n\n";
}
using Reg8 = Register<u8>;
using Reg16 = Register<u16>;
using Reg32 = Register<u32>;
using Reg64 = Register<u64>;
} // namespace vpc
In my main function where I'm using this class, the default constructor works, the second constructor works by passing in both values and variables. The third constructor is giving me a compiler error.
main.cpp
#include "Register.h"
int main() {
using namespace vpc;
u16 val = 0xC97B;
Reg8 r8low( val, 0 ); // should be 7B
Reg8 r8high( val, 1 ); // should be C9
std::cout << r8low << r8high;
return EXIT_SUCCESS;
}
This is the compiler error I'm getting from Visual Studio 2017:
1>------ Build started: Project: TestRegister, Configuration: Debug x64 ------
1>main.cpp
1>c:\***\register.h(38): error C2678: binary '&': no operator found which takes a left-hand operand of type 'int' (or there is no acceptable conversion)
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\cstddef(45): note: could be 'std::byte std::operator &(const std::byte,const std::byte) noexcept' [found using argument-dependent lookup]
1>c:\***\register.h(39): note: while trying to match the argument list '(int, _Ty)'
1> with
1> [
1> _Ty=std::make_unsigned<vpc::u8>
1> ]
1>c:\***\main.cpp(15): note: see reference to function template instantiation 'vpc::Register<vpc::u8>::Register<vpc::u16>(const P,const vpc::u8)' being compiled
1> with
1> [
1> P=vpc::u16
1> ]
1>c:\***\main.cpp(15): note: see reference to function template instantiation 'vpc::Register<vpc::u8>::Register<vpc::u16>(const P,const vpc::u8)' being compiled
1> with
1> [
1> P=vpc::u16
1> ]
1>Done building project "TestRegister.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I understand what the compiler error is; but I don't know what exact is causing it. Is it coming from std::size
or std::numeric_limits<...>()
? It does say left hand side so I'm assuming std::size()
...
I don't know how to resolve this. What can I do in order to be able to compile this? I'm almost certain if this constructor is causing this error, then my last constructor would probably cause the same or similar error.
Upvotes: 1
Views: 141
Reputation: 172934
Change std::make_unsigned<T>
to std::make_unsigned_t<T>
(or typename std::make_unsigned<T>::type
before C++14); You want the corresponding unsigned type, not std::make_unsigned
itself. i.e.
template<typename P>
Register(const P val, const u8 idx) :
data{ static_cast<T>((val >> std::size(bits) * idx) &
std::numeric_limits<std::make_unsigned_t<T>>::max()) },
// ^^
value{ data },
bits{ data }
{
assert(idx >= '\0' && idx < sizeof(T));
}
Upvotes: 1