经过一段时间的弄清楚我的问题后,我发现编译器如何从一组“标签”(非类型模板参数)中推导出模板参数真的很有趣。但看起来编译器只理解“逐字节”相等规则。
我的意思是这段代码:
struct S1 {
constexpr S1(int v) : _v(v)
{};
constexpr bool operator == (const S1& other) { return true;}
int _v;
};
template <S1 Tag, typename ValueType>
struct TagedValue { ValueType value; };
struct Test : TagedValue<S1{0}, int>, TagedValue<S1{1}, double> {};
template <S1 Idx, typename T>
auto& get(TagedValue<Idx, T>& test) {
return test.value;
}
int main()
{
Test test;
get<S1{1}>(test); // Still compiles, even though S1{0} == S1{1}
static_assert(S1{0} == S1{1});
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我已经定义了我自己的,operator ==
它基本上是说:“任何两个实例都是相等的”。但看起来为了在函数T
中推断get
,编译器仍然检查结构的实际内容是否相同。也就是说,S1{0} != S2{1}
即使S1{0} == S2{1}
从“C++ 的角度”来看,也是出于类型推导的目的。
我的问题是:有什么方法可以重新定义“类型推导相等规则”吗?
UPD:为了更清楚地说明,如果我替换这一行
struct Test : TagedValue<S1{0}, int>, TagedValue<S1{1}, double> {};
Run Code Online (Sandbox Code Playgroud)
和
struct Test : TagedValue<S1{1}, int>, TagedValue<S1{1}, double> {};
Run Code Online (Sandbox Code Playgroud)
编译器给出一个错误,抱怨歧义。
模板参数推导以及其他与模板相关的事物都使用类型等效的概念。与您的问题相关的部分是:
temp.type/1两个模板 ID相同,如果
...
(1.3) - 在转换为模板参数的类型后,它们相应的非类型模板参数是模板参数等效的(见下文)。 。temp.type/2如果两个值具有相同的类型,则它们是模板参数等效的
,并且 ...
(2.10) - 它们是类类型,并且它们相应的直接子对象和引用成员是模板参数等效的。
粗略地说,这是成员之间的平等。不,你不能覆盖它。