I want to write a template function that, given any class, will instantiate a new one but the template param is 1. I would like to do something like this:
template <uint COUNT>
class Foo {
using MY_NAME = Foo;
int data[COUNT];
void print();
}
template <class T>
void my_function(T in) {
auto x = in::MY_NAME<1>; // This somehow makes a XXX<whatever> into an XXX<1>.
x.print();
}
my_function(Foo<5>); // This should call Foo<1>.print();
I want to use templates or using
or something so that whatever input class I'm receiving, I make a new instance that is the same class but with a different template parameter.
Can this be done? It's all known at compile time so it seems like there ought to be a way to do it.
CodePudding user response:
Use a template template parameter. In this case, you would want to specify a non-type template parameter for the inner tempalte. That would look like
template <std::size_t COUNT>
struct Foo {
using MY_NAME = Foo;
int data[COUNT];
void print() { std::cout << "COUNT: " << COUNT; }
};
template <template<std::size_t> typename class_t, std::size_t N>
void my_function(class_t<N>) {
auto x = class_t<1>{}; // This somehow makes a XXX<whatever> into an XXX<1>.
x.print();
}
int main()
{
my_function(Foo<5>{}); // This should call Foo<1>.print();
}
and it outputs
COUNT: 1
as seen in this live example.
CodePudding user response:
I'm not sure it's possible to make the using declaration do what you want it to, making MY_NAME
refer to the injected template name Foo
instead of the injected class name Foo<COUNT>
. However you can make MY_NAME
be itself a template:
#include <iostream>
template <uint COUNT>
class Foo {
public:
template<uint C>
using MY_NAME = Foo<C>;
int data[COUNT];
void print() { std::cout << COUNT << '\n'; }
};
template <class T>
void my_function(T in) {
auto x = typename T::MY_NAME<1>{}; // Typename keyword is necessary here
x.print();
}
int main()
{
my_function(Foo<5>{}); // Prints 1
my_function(Foo<7>{}); // Prints 1
}
Demo here.
So now for any class template Bar
that exports its name via using MY_NAME
you can pass it to my_function
to call Bar<1>.print()
.
CodePudding user response:
Not sure what you need it for but the syntax you're looking could be this:
#include <array>
#include <iostream>
#include <utility>
template<std::size_t N>
struct Foo
{
// initialized array
std::array<int,N> data {};
// output all the values in the array
void print()
{
for (const int value : data) std::cout << value << " ";
}
};
template<typename type_t>
void my_function(const type_t& value)
{
std::cout << "my_function(" << value << ")\n";
// create a temporary and print it.
Foo<1>().print();
}
int main()
{
int v{ 5 };
my_function<int>(v);
}