3

I have simple code:

#include <iostream>

template<class... Types>
class A;

template<>
class A<> {
public:
    explicit A() {
        std::cout << "empty" << std::endl;
    }
};

template<class Head, class... Tail>
class A<Head, Tail...> {
public:
    explicit A(Head head, Tail ...tail) : tail_(tail...) {
        std::cout << head << std::endl;
    }

private:
    A<Tail...> tail_;
};


int main() {
    auto a = A(1, 2);
    return 0;
}

It doesn't compile:

test2.cpp:27:20: error: class template argument deduction failed:
     auto a = A(1, 2);
                    ^
test2.cpp:27: confused by earlier errors, bailing out

It could be fixed by adding deduction guide like:

template<class... T>
A(T...) -> A<T...>;

My question is why compiler can't resolve such simple case?

forward32
  • 61
  • 1
  • 1
  • 3
  • Perhaps the deduction is broken by template specialization? Looking up the constructor requires knowing which template specialization is to be used, which in this case requires looking at the constructor – jwimberley Nov 20 '19 at 15:45
  • Lots of similar questions, most just say "bug": https://stackoverflow.com/questions/43430921/deduction-guides-and-variadic-class-templates-with-variadic-template-constructor . Deducing from static factory function arguments seems to work well, so I'd recommend that as a workaround. – parktomatomi Nov 20 '19 at 15:46
  • 1
    Be carefull, here the standard is pretty important. I don't see `c++17` as tag of this question. – BiagioF Nov 20 '19 at 15:46
  • 1
    The recursiveness isn't crucial, btw; I can reproduce the issue if the only specializations are <> and – jwimberley Nov 20 '19 at 15:48

1 Answers1

3

Implicit deduction guides are only generated from the constructors of the primary class template. (C++17 [over.match.class.deduct]/1.1) You have not defined the primary class template.

Therefore, the class template partial specialization template<class Head, class... Tail> class A<Head, Tail...> ... is ignored when performing class template argument deduction. Writing an explicit deduction guide is a possible solution to this problem, as you have observed.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
  • Thank you for answer! So another way to fix it - specify constructor to the primary class template? – forward32 Nov 20 '19 at 16:13
  • 1
    @forward32 Yes, you could do that. But I think that defining the primary class template, when it is never going to be instantiated, is bad style. The explicit deduction guide would communicate intent better. – Brian Bi Nov 20 '19 at 16:48