C++ - The right way of type rebinding-resolving?
i have the following code snippets:
namespace X86X64
{
struct IMM8 {};
}
namespace X86
{
using namespace X86X64;
struct RM8 {};
template <class _Traits>
struct MOV_Instruction
{
typedef typename _Traits::RM8 RM8;
void mov(const RM8& rm, const IMM8& imm)
{}
};
}
namespace X64
{
using namespace X86X64;
struct RM8 {};
struct RM64 {};
struct Traits
{
typedef RM8 RM8;
};
struct MOV_Instruction : public X86::MOV_Instruction<Traits>
{
using X86::MOV_Instruction<Traits>::mov;
void mov(const RM64& rm, const IMM8& imm)
{}
};
}
When i use no traits, i get an error, that the compiler cannot find any operator converting an X64::RM8 to X86::RM8, when instantiating MOV_Instruction.
The namespaces X86 and X64 must have their own seperate RM8 types with different underlying base types.
I wanna only use an:
using namespace X86 | X64
MOV_Instruction i;
i.mov(RM8(), IMM8());
and want the compiler to select the right RM8 type depending on the used namespace and Koenig lookup. Is their a better way to do this without a trai开发者_高级运维ts to rebind or resolve the right type?
I could make X86::RM8 and X64::RM8 the same type, but i don't wanna strive for that.
Thanks Martin
This compiles fine using VC9:
namespace X86X64 {
struct IMM8 {};
}
namespace X86 {
using namespace X86X64;
struct RM8 {};
template <class Traits>
struct MOV_Instruction {
typedef typename Traits::RM8 RM8;
void mov(const RM8& rm, const IMM8& imm) {}
};
}
namespace X64 {
using namespace X86X64;
struct RM8 {};
struct RM64 {};
struct Traits {
typedef RM8 RM8;
};
struct MOV_Instruction : public X86::MOV_Instruction<Traits> {
using X86::MOV_Instruction<Traits>::mov;
void mov(const RM64& rm, const IMM8& imm) {}
};
}
int main()
{
//using namespace X86;
using namespace X64;
MOV_Instruction i;
i.mov(RM8(), IMM8());
return 0;
}
Note that can't have both using directives, since that would make MOV_Instruction
ambiguous.
Also, I changed _Traits
to Traits
, since identifiers starting with an underscore, followed by a capital letter, are reserved to the implementation. (You might attract a macro from some header to trample over your code and cause very strange compiler errors.)
One more way
namespace X86X64 { struct IMM8 {}; }namespace X86 { using namespace X86X64; typedef struct RM8 {} RM8;
template < class T = RM8 > struct MOV_Instruction { typedef T RM8; void mov(const RM8& rm, const IMM8& imm) {} };
}
namespace X64 { using namespace X86X64;
typedef struct RM8 {} RM8; struct RM64 {};
template < class T = RM8 > struct MOV_Instruction : public X86::MOV_Instruction { using X86::MOV_Instruction::mov;
void mov(const RM64& rm, const IMM8& imm) {}
}; }
int main() { using namespace X86;
MOV_Instruction<> i; i.mov(RM8(), IMM8()); return 0;
}
精彩评论