提问人:Francis Cugler 提问时间:6/12/2019 最后编辑:Francis Cugler 更新时间:6/12/2019 访问量:88
使用类模板的用户定义的赋值运算符时遇到问题 [已关闭]
Having trouble with user defined assignment operator for class template [closed]
问:
#include <iostream>
#include "Register.h"
int main() {
// Basic constructors
Reg8 r8{ 0xC4 };
Reg16 r16{ 0x1234 };
Reg32 r32{ 0x89ABCDEF };
Reg64 r64{ 0xABBA04200240ABBA };
// I can do this with similar types:
Reg8 r8b = r8; // okay
Reg16 r16b = r16; // okay
Reg32 r32b = r32; // okay
Reg64 r64b = r64; // okay
Reg8 r8c;
r8c = r8; // okay
Reg16 r16c;
r16c = r16; // okay
Reg32 r32c;
r32c = r32; // okay
Reg64 r64c;
r64c = r64; // okay
// Attempting with different Register Types.
// Now Fixed by doing the following:
// Reg16 r16d = r8; // Not okay - need to static_cast it.
Reg16 r16d = static_cast<Reg16>(r8); // okay
// What I would like to do:
Reg16 r16e;
r16e = r32; // not okay:
// NOTE: You can see some of my attempts of overloading
// specializing the operator=() below the class section.
return EXIT_SUCCESS;
}
注册.h
#pragma once
#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cstdint>
#include <iterator>
#include <iostream>
#include <iomanip>
#include <limits>
#include <map>
#include <string>
#include <type_traits>
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;
using Reg8 = Register<u8>;
using Reg16 = Register<u16>;
using Reg32 = Register<u32>;
using Reg64 = Register<u64>;
template<typename T>
struct Register {
T value;
T previous_value;
std::bitset<sizeof(T)* CHAR_BIT> bits;
Register() : value{ 0 }, previous_value{ 0 }, bits{ 0 } {}
template<typename V, std::enable_if_t<(sizeof(V) > sizeof(T))>* = nullptr>
explicit Register(const V val, const u8 idx = 0) :
value{ static_cast<T>((val >> std::size(bits) * idx) &
std::numeric_limits<std::make_unsigned_t<T>>::max()) },
previous_value{ 0 },
bits{ value }
{
constexpr u16 sizeT = sizeof(T);
constexpr u16 sizeP = sizeof(V);
assert((idx >= 0) && (idx <= ((sizeP / sizeT) - 1)) );
}
template<typename V, std::enable_if_t<(sizeof(V) < sizeof(T))>* = nullptr>
explicit Register(const V val, const u8 idx = 0) :
value{ static_cast<T>((static_cast<T>(val) << sizeof(V)*CHAR_BIT*idx) &
std::numeric_limits<std::make_unsigned_t<T>>::max()) },
previous_value{ 0 },
bits{ value }
{
constexpr u16 sizeT = sizeof(T);
constexpr u16 sizeP = sizeof(V);
assert((idx >= 0) && (idx <= ((sizeT / sizeP) - 1)) );
}
template<typename V, std::enable_if_t<(sizeof(V) == sizeof(T))>* = nullptr>
explicit Register(const V val, const u8 idx = 0) :
value{ static_cast<T>( val ) }, previous_value{ 0 }, bits{ value }
{}
// the explicit on the copy constructor was the culprit
template<typename V>
/*explicit*/ Register(const Register<V>& reg, const u8 idx = 0) : Register(reg.value, idx) {}
Register& operator=(const Register& obj) {
this->value = obj.value;
this->previous_value = obj.previous_value;
this->bits = obj.bits;
return *this;
}
};
} // namespace vpc
以下是一些重载的尝试 - 专门化 ,这些都是在我的班级声明中。operator=()
Reg8& operator=(const Reg16& rhs) {
Reg8 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
Reg8& operator=(const Reg32& rhs) {
Reg8 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
Reg8& operator=(const Reg64& rhs) {
Reg8 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
Reg16& operator=(const Reg8& rhs) {
Reg16 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
Reg16& operator=(const Reg32& rhs) {
Reg16 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
Reg16& operator=(const Reg64& rhs) {
Reg16 temp{ rhs };
this->value = temp.value;
this->previous_value = temp.previous_value;
this->bits = temp.bits;
return *this;
}
我相信应该有一种方法可以做到这一点,但我不确定如何做到这一点,如果我在这些重载的专用化方面走在正确的道路上,我不知道正确的语法,并且 Visual Studio 给了我这个编译器错误:
1>------ Build started: Project: TestRegister, Configuration: Debug x64 ------
1>main.cpp
1>c:\...\register.h(109): error C2556: 'vpc::Reg16 &vpc::Register<vpc::u8>::operator =(const vpc::Reg8 &)': overloaded function differs only by return type from 'vpc::Register<vpc::u8> &vpc::Register<vpc::u8>::operator =(const vpc::Register<vpc::u8> &)'
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u8>::operator ='
1>c:\...\main.cpp(23): note: see reference to class template instantiation 'vpc::Register<vpc::u8>' being compiled
1>c:\...\register.h(109): error C2371: 'vpc::Register<vpc::u8>::operator =': redefinition; different basic types
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u8>::operator ='
1>c:\...\register.h(85): error C2556: 'vpc::Reg8 &vpc::Register<vpc::u16>::operator =(const vpc::Reg16 &)': overloaded function differs only by return type from 'vpc::Register<vpc::u16> &vpc::Register<vpc::u16>::operator =(const vpc::Register<vpc::u16> &)'
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u16>::operator ='
1>c:\...\register.h(110): note: see reference to class template instantiation 'vpc::Register<vpc::u16>' being compiled
1>c:\...\register.h(85): error C2371: 'vpc::Register<vpc::u16>::operator =': redefinition; different basic types
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u16>::operator ='
1>c:\...\register.h(86): error C2079: 'vpc::Register<vpc::u16>::temp' uses undefined struct 'vpc::Register<vpc::u8>'
1>c:\...\register.h(87): error C2059: syntax error: 'this'
1>c:\...\register.h(87): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(88): error C2059: syntax error: 'this'
1>c:\...\register.h(88): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(89): error C2059: syntax error: 'this'
1>c:\...\register.h(89): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(90): error C2059: syntax error: 'return'
1>c:\...\register.h(90): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(93): error C2143: syntax error: missing ';' before ''symbol''
1>c:\...\register.h(111): error C2059: syntax error: 'this'
1>c:\...\register.h(111): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(112): error C2059: syntax error: 'this'
1>c:\...\register.h(112): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(113): error C2059: syntax error: 'this'
1>c:\...\register.h(113): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(114): error C2059: syntax error: 'return'
1>c:\...\register.h(114): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(117): error C2143: syntax error: missing ';' before ''symbol''
1>c:\...\main.cpp(29): error C2679: binary '=': no operator found which takes a right-hand operand of type 'vpc::Reg8' (or there is no acceptable conversion)
1>c:\...\register.h(78): note: could be 'vpc::Register<vpc::u16> &vpc::Register<vpc::u16>::operator =(const vpc::Register<vpc::u16> &)'
1>c:\...\main.cpp(29): note: while trying to match the argument list '(vpc::Reg16, vpc::Reg8)'
1>c:\...\register.h(101): error C2556: 'vpc::Reg8 &vpc::Register<vpc::u64>::operator =(const vpc::Reg64 &)': overloaded function differs only by return type from 'vpc::Register<vpc::u64> &vpc::Register<vpc::u64>::operator =(const vpc::Register<vpc::u64> &)'
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u64>::operator ='
1>c:\...\main.cpp(141): note: see reference to class template instantiation 'vpc::Register<vpc::u64>' being compiled
1>c:\...\register.h(101): error C2371: 'vpc::Register<vpc::u64>::operator =': redefinition; different basic types
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u64>::operator ='
1>c:\...\register.h(103): error C2059: syntax error: 'this'
1>c:\...\register.h(103): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(104): error C2059: syntax error: 'this'
1>c:\...\register.h(104): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(105): error C2059: syntax error: 'this'
1>c:\...\register.h(105): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(106): error C2059: syntax error: 'return'
1>c:\...\register.h(106): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(109): error C2143: syntax error: missing ';' before ''symbol''
1>c:\...\register.h(93): error C2556: 'vpc::Reg8 &vpc::Register<vpc::u32>::operator =(const vpc::Reg32 &)': overloaded function differs only by return type from 'vpc::Register<vpc::u32> &vpc::Register<vpc::u32>::operator =(const vpc::Register<vpc::u32> &)'
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u32>::operator ='
1>c:\...\main.cpp(142): note: see reference to class template instantiation 'vpc::Register<vpc::u32>' being compiled
1>c:\...\register.h(93): error C2371: 'vpc::Register<vpc::u32>::operator =': redefinition; different basic types
1>c:\...\register.h(78): note: see declaration of 'vpc::Register<vpc::u32>::operator ='
1>c:\...\register.h(95): error C2059: syntax error: 'this'
1>c:\...\register.h(95): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(96): error C2059: syntax error: 'this'
1>c:\...\register.h(96): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(97): error C2059: syntax error: 'this'
1>c:\...\register.h(97): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(98): error C2059: syntax error: 'return'
1>c:\...\register.h(98): error C2238: unexpected token(s) preceding ';'
1>c:\...\register.h(101): error C2143: syntax error: missing ';' before ''symbol''
1>Done building project "TestRegister.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
我尝试了很多其他方法,我搜索了谷歌,我在这里搜索了其他问答,但似乎找不到任何与我的情况相关的内容,除非我忽略了什么。我必须做些什么才能编译它?
编辑
复制构造函数和赋值运算符都失败了,因为 上忽略了 。这给了我大量的 Visual Studio 编译器错误。删除那个明确的关键字,解决了所有问题。而我上面的班级就是所需要的。甚至根本不需要类部分下方的重载或专业化。3个多小时试图弄清楚这一点......explicit
Copy Constructor
operator=()
答:
2赞
max66
6/12/2019
#1
如果我正确理解您的代码,那么不同类型的代码很简单operator=()
Register<T>
template <typename U>
Register & operator= (Register<U> const & obj)
{ return *this = Register{obj}; }
但是当你写
Reg16 r16c = r8;
你打电话给施工者,而不是.operator=()
在我看来,你必须删除explicit
template<typename V>
explicit Register(const Register<V>& reg, const u8 idx = 0) : Register(reg.value, idx) {}
您还必须更正 main,因为它是引用,而不是指针;所以你必须使用点运算符,而不是箭头运算符operator=()
obj
Register& operator=(const Register& obj) {
this->value = obj.value; // not obj->value
this->previous_value = obj.previous_value; // not obj->previous_value
this->bits = obj.bits; // not obj->bits
return *this;
};
顺便说一句:你的主线不等于默认?operator=()
operator=()
评论
0赞
Francis Cugler
6/12/2019
我更新了我的问题,我仍然想保持明确。我必须用它来使赋值构造函数工作。但是我仍然有问题。static_cast<type>(obj)
0赞
max66
6/12/2019
@FrancisCugler - 如果你想维护它,你必须写 .无论如何,你的主要.答案已改进。explicit
Reg16 r16c = Reg16{r8};
operator=()
0赞
Francis Cugler
6/12/2019
是的,我注意到了这一点,并在我的源代码中修复了它。
0赞
max66
6/12/2019
@FrancisCugler - 通过更正,并添加我的模板,在我的平台中编译。operator=()
Reg16 r16d; r16d = r8;
1赞
Lightness Races in Orbit
6/12/2019
explicit
在复制构造函数上很奇怪。弗朗西斯,你为什么要保留它?
评论
operator=
Reg16 r16c = r8;
Reg16 r16c(static_cast<Reg16>(r8));