Home > Software engineering >  How to define equivalent rule for non type template arg
How to define equivalent rule for non type template arg

Time:11-04

After some time of figuring out my question I have found it's really fascinating how compiler can deduce template arguments from set of "tags" (non-type template args). But it looks like the compiler only understands "byte by byte" equality rule.

What I mean is this code:

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});
}

As you can see I have defined my own operator == which basically says: "any two instances are equal". But it looks like in order to deduce T in get function the compiler still checks whether or not the actual content of the struct is the same. That is, for the purpose of type deduction S1{0} != S2{1}, even though S1{0} == S2{1} from "C point of view".

My question is: Is there any way I can redefine that "type deduction equality rule"?

UPD: To make it probably more clear, if I replace this line

    struct Test : TagedValue<S1{0}, int>, TagedValue<S1{1}, double> {};

with

    struct Test : TagedValue<S1{1}, int>, TagedValue<S1{1}, double> {};

the compiler gives an error, complaining about ambiguty.

CodePudding user response:

Template parameter deduction, and other template-related things, use the concept of type equivalence. The parts relevant to your question are these:

temp.type/1 Two template-ids are the same if
...
(1.3) - their corresponding non-type template-arguments are template-argument-equivalent (see below) after conversion to the type of the template-parameter...

temp.type/2 Two values are template-argument-equivalent if they are of the same type and
...
(2.10) - they are of class type and their corresponding direct subobjects and reference members are template-argument-equivalent.

Roughly, it's member-wise equality. No, you cannot override it.

CodePudding user response:

You can not override the equality check for template parameter objects:

An identifier that names a non-type template parameter of class type T denotes a static storage duration object of type const T, called a template parameter object, whose value is that of the corresponding template argument after it has been converted to the type of the template parameter. All such template parameters in the program of the same type with the same value denote the same template parameter object. A template parameter object shall have constant destruction.

https://en.cppreference.com/w/cpp/language/template_parameters

  • Related