如何为非类型模板arg定义等效规则

Dmi*_*try 2 c++ c++20

经过一段时间的弄清楚我的问题后,我发现编译器如何从一组“标签”(非类型模板参数)中推导出模板参数真的很有趣。但看起来编译器只理解“逐字节”相等规则。

我的意思是这段代码:

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)

编译器给出一个错误,抱怨歧义。

Igo*_*nik 5

模板参数推导以及其他与模板相关的事物都使用类型等效的概念。与您的问题相关的部分是:

temp.type/1两个模板 ID相同,如果
...
(1.3) - 在转换为模板参数的类型后,它们相应的非类型模板参数是模板参数等效的(见下文)。 。

temp.type/2如果两个值具有相同的类型,则它们是模板参数等效的
,并且 ...
(2.10) - 它们是类类型,并且它们相应的直接子对象和引用成员是模板参数等效的。

粗略地说,这是成员之间的平等。不,你不能覆盖它。