0

I have the following error message from this question, class template deducation guide for struct-based parameters.

<source>:44:8: error: template parameters not deducible in partial specialization:
   44 | struct A3<int> : A<N> {
      |        ^~~~~~~
<source>:44:8: note:         'N'
Compiler returned: 1

How can I view the deduction guides for A3 and A?

Edit: removed invalid excerpt. Well, the comment discussion got horribly sidetracked. The rules for generating implicit deduction guides can be complicated, especially for aggregates. I think it would be useful to be able to see any guides which have been automatically generated, especially if you are new to C++ and want to tweak the implicit guides. That's why this question is important even if the excerpt was invalid.

user19087
  • 1,899
  • 1
  • 16
  • 21
  • 2
    I don't think CTAD (and deduction guides) matter for partial specialization. – HolyBlackCat Jun 11 '22 at 22:30
  • So, there's nothing I can do to fix that `A3` specialization? I'd still like to see the current guides though, just in case. – user19087 Jun 11 '22 at 22:40
  • Can you actually show the specialization, as a [mcve]? About the deduction guides - If your IDE doesn't show them (I don't think mine does), you could parse your code with something like libclang. Or grep for `-> A3`. – HolyBlackCat Jun 11 '22 at 22:45
  • @HolyBlackCat: 1) Done 2) Don't see any deduction guides on *godbolt.org* 3) libclang? 4) Don't see anything like `-> A3` on *godbolt.org*. – user19087 Jun 11 '22 at 22:51
  • I thought you were asking how to search for custom deduction guides. If you meant the implicit guides, [cppreference](https://en.cppreference.com/w/cpp/language/class_template_argument_deduction#Implicitly-generated_deduction_guides) explains how those are generated. – HolyBlackCat Jun 11 '22 at 23:05
  • 1
    What do you expect `template struct A3` to do? It has the syntax of a partial specialization, but it doesn't use `N`, so it can't work. This whole thing has nothing to do with deduction guides or CTAD at all. The declaration itself doesn't work. – user17732522 Jun 11 '22 at 23:07
  • You have some misunderstanding of how partial specialization works. It's supposed to apply for a subset of possible template arguments, and is chosen based on template arguments alone. You can't get `3` from `int`. I don't think you need partial specialization at all, just `template struct A3` as a primary template should work. – HolyBlackCat Jun 11 '22 at 23:08
  • The issue with that approach, is that I'd have to specify `A3` where `3` is redundant since it can be deduced from the constructor. But I wouldn't be able to just say `A3`. Technically, the `A3` specialization as-is applies for a subset (`int` is a subset of `T`), and is chosen based on the template argument alone (`A3`). I know what you mean though. I have a working specialization (compiles & runs) very similar to `A3` which has several type parameters which are used to *restrict* (and match against) the specialization argument. – user19087 Jun 11 '22 at 23:25
  • But just because `N` doesn't restrict anything doesn't mean its syntactically incorrect or can't be deduced. I don't want to get '`3` from `int`', I want to select the partial specialization then deduce `N` from the constructor. Normally a new template instance is created for each unique set of template arguments which match the specialization. Result - multiple instances of the specialization. Here a new instance is created for each unique set of matching template arguments, plus a new template parameter `N`. Result - multiple instances of the specialization. There's nothing new. – user19087 Jun 11 '22 at 23:45
  • @HolyBlackCat: '... cppreference explains how those are generated'. Yes but that is tedious especially for aggregate types. – user19087 Jun 11 '22 at 23:45
  • Point is, I believe a template deduction guide can fix this. – user19087 Jun 11 '22 at 23:58
  • @user19087: `A3` is a **class** (as a specialization of `A3`), not a class template. It therefore has no template parameters to deduce. – Davis Herring Jun 12 '22 at 00:10
  • If it was a class, I should be able to template it, no? – user19087 Jun 12 '22 at 00:56
  • @user19087 `A3` is already the class template. There is no way to have only some template parameters be deduced for class templates. It doesn't work like it does for function templates. If you specify a template argument list then there will be no deduction on class templates at all. – user17732522 Jun 12 '22 at 01:26
  • That's what I said about @HolyBlackCat's proposal, except it would have to be `template struct A3` because I really do need the specialization for something else. And like we said, `A3` disables all template deduction. Unless you have some idea how I could combine a partial argument list in a `using` statement with a deduction guide... – user19087 Jun 12 '22 at 01:35
  • @user19087 The point is that what you are trying to do is impossible with class templates. You can write one or multiple function templates similar to `std::make_array` which are less restricted on what deductions are possible, but it is not possible with class templates. The syntax `A3(a)` will always produce the same type `A3` if `A3` is a class template, no matter what the type of `a` is or what specializations you declare. (Or I don't understand what the goal is.) – user17732522 Jun 12 '22 at 01:47
  • Wait, you're saying that the template argument list in `A3` disables the deduction of `template `? That's why its not working, even with a custom deduction guide? – user19087 Jun 12 '22 at 01:57
  • Specifying any template argument list `<...>` explicitly at all on a class template name disable all class template argument deduction, yes. That's what I mean when I say that it works differently than for function templates, where deduction would still be done if not all template parameters were explicitly specified. – user17732522 Jun 12 '22 at 02:05
  • And as I said earlier the partial specialization doesn't make sense at all. Class template argument deduction decides what the arguments `...` in `A3<...>` ought to be if you left out `<...>`. Only _after_ deciding that are partial specializations considered to decide what the _definition_ for this particular `A3<...>` ought to be. The template parameters in the partial specialization are deduced _from `<...>`_, not a constructor or anything else. Partial specializations don't do anything but changing the definition for some specific sets of template arguments. – user17732522 Jun 12 '22 at 02:05
  • Why do you insist on writing ``? It can be deduced, together with 3. (Exactly like `std::array` deduces both size and type). – HolyBlackCat Jun 12 '22 at 07:35
  • I understand, but I don't like it. I wonder if partial CTAD will be part of C++2b. The function template wrapper seems to work, but I'm curious if there other workarounds. – user19087 Jun 13 '22 at 09:13
  • @HolyBlackCat: `` is a placeholder for a more complicated specialization. – user19087 Jun 13 '22 at 09:14
  • regarding partial CTAD: https://stackoverflow.com/questions/57563594/partial-class-template-argument-deduction-in-c17 , https://stackoverflow.com/questions/41833630/c17-class-template-partial-deduction – bolov Jun 14 '22 at 00:05

1 Answers1

1

You can generate the AST tree from clang. It shows a bunch on things like implicitly declared special methods (default constructors etc.) as well as implicit deduction guides. The deduction guides however seem to be shown only when they are actually used to deduce a template. I am not familiar with the tool and couldn't tell you if there is a way to show them regardless.

E.g. for this code:

template <class T>
struct A
{
  A(T a) : a_{a} {}
  T a_;
};

auto test()
{
    auto a = A{24}; // without this the deduction guides are not shown
}

This is the relevant output:

TranslationUnitDecl
|
| ...
|
|-FunctionTemplateDecl <line:1:1, line:4:19> col:3 implicit <deduction guide for A>
| |-TemplateTypeParmDecl <line:1:11, col:17> col:17 referenced class depth 0 index 0 T
| |-CXXDeductionGuideDecl <line:4:3, col:19> col:3 implicit <deduction guide for A> 'auto (T) -> A<T>'
| | `-ParmVarDecl <col:5, col:7> col:7 a 'T'
| `-CXXDeductionGuideDecl <col:3, col:19> col:3 implicit used <deduction guide for A> 'auto (int) -> A<int>'
|   |-TemplateArgument type 'int'
|   | `-BuiltinType 'int'
|   `-ParmVarDecl <col:5, col:7> col:7 a 'int':'int'
`-FunctionTemplateDecl <line:1:1, line:2:8> col:8 implicit <deduction guide for A>
  |-TemplateTypeParmDecl <line:1:11, col:17> col:17 referenced class depth 0 index 0 T
  `-CXXDeductionGuideDecl <line:2:8> col:8 implicit <deduction guide for A> 'auto (A<T>) -> A<T>'
    `-ParmVarDecl <col:8> col:8 'A<T>'

You can see "implicit <deduction guide for A > auto (T) -> A<T>".

Play with it on godbolt or generate it yourself.

Another tool is cppinsight (which is built from clang also). It only shows the "specialization" of the deduction guide if it's used:

/* First instantiated from: insights.cpp:10 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
A(int a) -> A<int>;
#endif
bolov
  • 72,283
  • 15
  • 145
  • 224