================
@@ -1216,10 +1308,225 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
->getDeductionCandidateKind() == DeductionCandidate::Aggregate)
continue;
- BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc);
+ BuildDeductionGuideForTypeAlias(SemaRef, AliasTemplate, F, Loc,
+ DeducingTemplate, DerivedClassMapperType);
}
}
+void DeclareImplicitDeductionGuidesFromInheritedConstructors(
+ Sema &SemaRef, TemplateDecl *Template, ClassTemplateDecl *Pattern,
+ TypeSourceInfo *BaseTSI, unsigned BaseIdx) {
+ auto &Context = SemaRef.Context;
+ DeclContext *DC = Template->getDeclContext();
+ const auto *BaseTST =
BaseTSI->getType()->getAs<TemplateSpecializationType>();
+ if (!BaseTST)
+ return;
+ SourceLocation BaseLoc = BaseTSI->getTypeLoc().getBeginLoc();
+
+ TemplateDecl *BaseTD = BaseTST->getTemplateName().getAsTemplateDecl();
+ if (!BaseTD)
+ return;
+
+ // Subsitute any parameters with default arguments not present in the base,
+ // since partial specializations cannot have default parameters
----------------
antangelo wrote:
Consider this example:
```c++
template<class T>
struct Base {
Base(T t);
};
template<class InBase = int, class NotInBase = int>
struct A : public Base<InBase> {
using Base<InBase>::Base;
};
A a(10);
```
(accepted by gcc: https://godbolt.org/z/jbj1WMq9d)
To my understanding of the standard, we should generate:
```c++
template<class InBase = int, class NotInBase = int>
using Alias = Base<InBase>;
template<typename T> class CC;
template<typename InBase, typename NotInBase>
class CC<Base<InBase>> {
typedef A<InBase, NotInBase> type;
};
```
along with the transformed alias deduction guides. With these in place, that
deduction will fail, because it is not possible to instantiate the partial
specialization of `CC<R>` for the deduction guide return type `R` (which is
`Base<InBase>` in practice).
The reason this substitution fails is because `NotInBase` cannot be determined
from `Base<InBase>`. Since partial specializations cannot have default
arguments, the fact that `NotInBase` is defaulted in the derived class is not
respected.
The solution I came up with for this problem is to rewrite the template
parameters to substitute in these template arguments which have defaults in the
derived class, but do not appear in the base. Then, the partial specialization
member typedef can refer to them directly. In practice, these arguments cannot
be deduced to anything else anyway.
This issue does not exist for defaulted parameters that do appear in the base--
those will substitute fine into the partial specialization. I also opted not to
bail in the case where there is a template parameter with no default that does
not appear in the base; the template is not deducible in this case, but I opt
to generate a deduction guide anyway so we can emit a diagnostic.
The TPL does indeed still contain the default arguments, but clang's
implementation as it is will ignore them. I agree that we probably shouldn't
rely on this, though.
https://github.com/llvm/llvm-project/pull/98788
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits