Home > Blockchain >  How can I declare a new variable of the same class but with different template parameters in c ?
How can I declare a new variable of the same class but with different template parameters in c ?

Time:10-02

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);
}
  • Related