C++ variadic templates with type and non-type argument mixing for recursive inheritance
It's not possible. You'll have to settle for one of the following:
Foo<Bar<int, 5>, Bar<double, 7>> foo_1;
Foo<int, Bar<5>, double, Bar<7>> foo_1;
// ...?
If the values are always integral, you could also try this:
Foo<int[5], double[7]> foo_1;
And then extract elemenet types & extents from each argument.
How do I do variadic templates of variadic arguments
The fact that ColumnValue
is a template doesn't make any difference for the signature of print
. We can just take a regular parameter pack and let the compiler figure out the different types.
Secondly we can't loop over a parameter pack. We can however use a fold-expression.
The end result would look something like this
template <typename... T>
void print(std::string firstArg, const T& ...args) {
(std::cout << ... << args.value) << std::endl;
}
If you want to insert a newline between each argument, you would need some kind of helper for that. The simplest idea would be.
template <typename T>
void print_helper(const T& arg) {
std::cout << arg << '\n';
}
template <typename... T>
void print(std::string firstArg, const T& ...args) {
(print_helper(args.value), ...);
}
Creating a base case for Variadic Template recursion with no template arguments
Here's another solution (without specialization), which uses a C++20 requires
clause to resolve the ambiguity:
template <typename... Args> requires (sizeof...(Args) == 0)
constexpr int NumArguments() {
return 0;
}
template<typename FirstArg, typename... RemainingArgs>
constexpr int NumArguments() {
return 1 + NumArguments<RemainingArgs...>();
}
Example:
int main() {
std::cout << NumArguments<int>() << std::endl;
std::cout << NumArguments() << std::endl;
std::cout << NumArguments<float, int, double, char>() << std::endl;
return 0;
}
1
0
4
EDIT:
My old suggestion using concepts
was incorrect. There's a good post here on using concepts and parameter packs.
Variadic template packed argument to std::vector
Another, slightly more wordy, way to do this is to add an initial template parameter specifying the type of vec
, like so:
#include <iostream>
#include <vector>
template <typename T, typename ... Args>
void int_printf(Args ... args)
{
std::vector<T> vec = {args...};
for (auto& v : vec)
{
std::cout << v << std::endl;
}
}
int main()
{
int_printf<int>(1,2,3,4);
return 0;
}
This might give clearer error messages if you pass a list of incompatible types to int_printf
.
Pattern matching with variadic templates and default argument
It's basically the same as with default function arguments: You can only omit parameters from the right. And I don't expect this to change, also because what you want to do can be achieved by adding a layer of indirection:
template<bool DebugMode=false>
struct Wrap {
template <typename ...T> struct A {};
};
template <typename...T> using A = Wrap<>::A<T...>;
int main() {
A<double, double> a;
}
Alternatively:
template <bool DebugMode=false,typename ...T>
struct A_impl {};
template <typename...T>
using A = A_impl<false,T...>;
Though here the default false
cannot be really used, for the using
you still have to specify it.
Related Topics
Why Is Std::Iterator Deprecated
Why Is "Operator Void" Not Invoked with Cast Syntax
Lifetime of Lambda Objects in Relation to Function Pointer Conversion
Distinguish Between Single and Double Click Events in Qt
Checking for Underflow/Overflow in C++
Why Can't I Do Polymorphism with Normal Variables
Is There Any Reason to Use C Instead of C++ for Embedded Development
Copying Std::Vector: Prefer Assignment or Std::Copy
Initializing Std::String from Char* Without Copy
How to Find Out If a Tuple Contains a Type
How to Know If a Type Is a Specialization of Std::Vector
_Iterator_Debug_Level Value '0' Doesn't Match Value '2'
How to Make Gcc Warn on Passing Too-Wide Types to Functions
Convert String with Explicit Escape Sequence into Relative Character
C++ Add Months to Chrono::System_Clock::Time_Point
Performance Tradeoff - When Is Matlab Better/Slower Than C/C++