#include <cstddef>
#include <utility>
template <size_t N, typename... V>
struct T {
int test(size_t n, const char** ss) {
if (N > n)
return 1;
return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
return test_impl(ss[I]...);
}(ss, std::make_index_sequence<N>{});
}
// Ideally this would be templated, solving my problem:
// i.e. move "typename... V" from the struct to this function.
virtual int test_impl(V...) = 0;
};
template <typename U, size_t N, typename... V>
struct T1 : T<N, V...> {
U value;
int (*tester)(U*, V...);
int test_impl(V... v) {
return tester(&value, v...);
}
// virtual is not an aggregate
T1(U value, int (*tester)(U*, V...))
: value{value}, tester{tester}
{};
};
int test1(int* v, const char* s1, const char* s2) {
return 1;
}
template <typename... V>
int test2(int* v, V... ss) {
return 1;
}
C is very good at deducing template function parameters from function arguments, but virtual function templates are not allowed. I am forced to move the function template parameters to the struct template, and find that C is not good at deducing template struct parameters from member variables. In the end I am forced to specify redundant information to the template which makes the T1
/T
interface difficult to use? How can I fix this?
For example, here we know that:
sizeof...(V) == N
decltype(V)
must beconst char*
- template parameter
U
can be deduced solely from the argument of theT1
constructor - template parameter
V...
can be deduced solely from the argument of theT1
constructor - from which it follows that template parameter
N
can be deduced solely from the argument of theT1
constructor.
int main() {
// The '2' and the 'const char*'... are redundant
T1 a = T1<int, 2, const char*, const char*>(10, test1);
T1 b = T1<int, 2, const char*, const char*>(10, test2);
// There is enough information here to deduce the values
T1 c = T1(10, test1);
// There is enough information here to deduce the values
T1 d = T1<..., 2, ...>(10, test2);
}
CodePudding user response:
sizeof...(V) == N
No, the compiler doesn't know it. (Take a look at the error messages)
Since you have this prequisite, you don't have to have the template parameter N
.
template <typename... V>
struct T {
int test(size_t n, const char** ss) {
constexpr int N = sizeof...(V);
if (N > n)
return 1;
return []<size_t... I>(const char* ss[N], std::index_sequence<I...>) {
return test_impl(ss[I]...);
}(ss, std::make_index_sequence<N>{});
}
// Ideally this would be templated, solving my problem:
// i.e. move "typename... V" from the struct to this function.
virtual int test_impl(V...) = 0;
};
See online demo