David Spry
David Spry

Reputation: 149

Why does template-argument deduction work differently for function-templates compared to class-templates (via their constructors)?

I have a class structured like this, where FixedStr is implicitly constructible from a string-literal:

template<FixedStr K, class... T>
struct ParserCtx {
  Parser<T...> parser;

  ParserCtx(std::string_view description, Parser<T...>&& parser)
    : parser(std::move(parser))
  {}
};

I intended to use it in the following way, with T being deduced from invocations of the constructor.

ParserCtx<"name">{"desc", Parser{1, 2.0, 3.0f}};

However, as you know, this doesn't work, because CTAD is all-or-nothing. From cppreference:

Class template argument deduction is only performed if no template argument list is present. If a template argument list is specified, deduction does not take place.

I was surprised to find that this isn't true of function-templates, so the usage described above can be 'emulated' using function-templates.

template<FixedStr K, class... T>
auto ParserCtx(std::string_view desc, Parser<T...>&& parser) -> impl::ParserCtx<K, T...> {
  return {desc, std::move(parser)};
}

ParserCtx<"name">("desc", Parser{1, 2.0, 3.0f});

However, it occurred to me that I'd actually seen this many times before when using 'helper' functions like std::to_array.

std::array<int>{1, 2, 3}; // N is not deduced
std::to_array<int>({1, 2, 3}); // N is deduced

Why does argument deduction behave differently in these different contexts?

Upvotes: 1

Views: 34

Answers (0)

Related Questions