I am using a c++2a feature which allows structs / std::array as template arguments (g++-9.2.0
, not supported in clang
yet).
The feature is called Class types in non-type template parameters
and proposed in P0732R2
.
I try to use templates parameters of one class (struct C
in the examples below) in order to deduce corresponding class template parameters of a second class (struct B
in the examples below). I hereby make use of a custom class template parameter deduction guide I wrote for that specific purpose.
In this minimal example, the information I want to extract are two int
s.
If I use these primitive types as template parameters, everything works fine. However, when I combine the information in one std::pair
or a custom std::struct
, the deduction fails.
The code below works just fine.
#include <array>
/// Data structure which contains a constexpr context to be used for type deduction later
template <int aa, int ab> struct C {};
/// Class which has to find out its own type
template <std::size_t count, std::array<int, count> a, std::array<int, count> b> struct B {
template <int... aa, int... bb> explicit B(C<aa, bb> ... c) {}
};
/// Class deduction guide
template <int... aa, int... ab> B(C<aa, ab>... c)
->B<sizeof...(aa) + 1, std::array<int, sizeof...(aa) + 1>{aa...},
std::array<int, sizeof...(aa) + 1>{ab...}>;
int main() { B k{C<1, 2>{}, C<2, 3>{}}; }
The code below fails to compile.
#include <array>
/// Change: A contains the information from the previous example in a structs.
struct A { int a; int b; };
/// Data structure which contains a constexpr context to be used for type deduction later
template <A a> struct C {};
/// Class which has to find out its own type
template <std::size_t count, std::array<A, count> a> struct B {
template <A... af> explicit B(C<af> ... c) {}
};
/// Class deduction guide
template <A... af> B(C<af>... c)->B<sizeof...(af) + 1, std::array<A, sizeof...(af) + 1>{af...}>;
int main() { B k{C<A{1, 2}>{}, C<A{2, 3}>{}}; }
The error output:
main.cc: In function ‘int main()’:
main.cc:24:14: error: class template argument deduction failed:
24 | B k {c1, c2};
| ^
main.cc:24:14: error: no matching function for call to ‘B(C<A{1, 2}>&, C<A{1, 2}>&)’
main.cc:17:20: note: candidate: ‘B(C<((const A)af)>...)-> B<(sizeof... (af) + 1), std::array<A, (sizeof... (af) + 1)>{(const A)af ...}> [with A ...af = {}]’
17 | template <A... af> B(C<af>... c)->B<sizeof...(af) + 1, std::array<A, sizeof...(af) + 1>{af...}>;
| ^
main.cc:17:20: note: candidate expects 0 arguments, 2 provided
main.cc:14:31: note: candidate: ‘template<long unsigned int count, std::array<A, count> a, A ...af> B(C<((const A)af)>...)-> B<count, a>’
14 | template <A... af> explicit B(C<af> ... c) {}
| ^
main.cc:14:31: note: template argument deduction/substitution failed:
main.cc:24:14: note: couldn’t deduce template parameter ‘count’
24 | B k {c1, c2};
I now wonder what causes this problem. Does the error occur because
I also do not understand the error message. It seems like zero arguments are expected for the function. Is the problem that C<af>...
cannot be expanded in the constructor?
@AndiG and @walnut anwered my question with their comments to my original question.
My issue is probably caused by a bug in my version of G++-9
. I currently do not use the newest version of g++-9
, the bug is solved at least in g++-10. In the version of g++-10.0
I compiled (3684bbb022c
) I do not receive the error anymore.