c++templatestemplate-argument-deduction

Template deduction guide doesn't work well with aggregate initialization


I am studying how to use deduction guides. I composed this program.

template<typename T>
struct Test {
    void f() {
        cout << std::is_same_v<T, std::size_t> << endl;
    }
    T t;
};

Test(int) -> Test<std::size_t>;

int main() {
    Test t1(1.2);
    t1.f();
}

I expected the deduction guide will only kick in when if I pass an integer to the aggregate initialization. Since I pass 1.2, I expected T will be deducted to double which won't triggered the deduction guide. However the output is 1, i.e. T -> int -> size_t.

I tried to add a constructor to the struct.

template<typename T>
struct Test {
    void f() {
        cout << std::is_same_v<T, std::size_t> << endl;
    }
    Test(T v): t(v) {}
    T t;
};

Test(int) -> Test<std::size_t>;

int main() {
    Test t1(1.2);
    t1.f();
}

The output was 0 which matched my previous expectation. Comparing these two programs, the only difference here is how the struct got initialized. What does the deduction guide not work well with the aggregate initialization? Thanks.


Solution

  • Deduction guide works like a overload resolution for a function.

    So when you have written deduction guide like this:

    Test(int) -> Test<std::size_t>;
    

    When constructing Test wiht deduction type, compiler will do:

    So you have to create deduction overload which will kick in before conversion or promotion is applied. You need exact match. So solution is simple add template deduction gude which will catch everything else:

    
    template<typename T>
    Test(T) -> Test<T>;
    Test(int) -> Test<std::size_t>;
    

    https://godbolt.org/z/rhqP146jn

    Now compiler when he can't find exact match without template, but can use tempted deduction guide which lead to perfect argument type match.