2
votes

C++17 offers class template argument deduction.

I have the following small example (you can paste into onlinegdb with C++17 enabled, no problem) where it fails under certain circumstances but I do not know why:

#include <iostream>
enum class Res{
    ResA,
    ResB
};

template<Res>
class B{   
};

template<Res T>
class A{
    //If I remove this construtor, template type deduction will not work anymore
    public:   
    A(B<T> b){       
    }
};

template<>
class A<Res::ResA>{
    public:
    A(B<Res::ResA> b){
        std::cout<<"A res A\n";
    }  
};

int main()
{
    B<Res::ResA> b;
    A a(b);
}

The code above works. But as soon as I change A's constructor to be the any other constructor than in the template specializations, the template argument deduction will not work and A has to be initialized by A<Res::ResA>.

I am at loss. Why could this be the case? Thank you for any ideas!

1
I guess the compiler ignores the specializations for argument deduction. So there's no way it would know what T should be.user253751
FWIW, to keep yourself sane, when you have a template specialization, pretend that it doesn't exist. They don't actually come into play until the primary template is resolved and are only used with the primary template matches the template specialization. Until then, all it is is just a recipe for those particular template parameters.NathanOliver
Elliot, what difference does this make semantically?Theodor Johnson
@Elliott There is no deduction in that case, there is only a default value for the template parameter so it would only make the code work for that specific specialization. That doesn't really answer the question or solve any issues with CTAD. It only makes this specific snippet of code compile.super
@Elliott No, the compiler doesn't deduce anything. You are telling it explicitly that the template parameter should be Res::ResA if it's not deducable. If you would add another template specialization A<Res::ResB> that takes an B<Res::ResB> in it's constructor it wouldn't work since there is not actual deduction involved. Only a default value.super

1 Answers

4
votes

Generated CTAD are only from primary template.

If you don't want to add that constructor in primary template, you can still provide custom deduction guide.