Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use an object instance as template argument?

Tags:

c++

templates

I'm learning C++. I have a Classroom class which should behave one way or another depending on the Configuration object that is being used. I could pass that Configuration object in the constructor when creating the Classroom object like this:

class Classroom {
private:
    Configuration conf;
public:
    Classroom(Configuration conf_){
        conf = conf_;
    }
    /** more member functions that use conf **/
};

But I thought it would be cooler if I could use a template for it. The Configuration object would be passed as template argument when creating the Classroom object. This is what I came up with, but it doesn't work:

template<Configuration &conf>
class Classroom {
    int doSomething(int n){
        // member function that uses data in Configuration object
        return n + conf.config_1;
    }
};

struct Configuration {
public:
    int config_1;
};

int main() {
    Configuration conf;
    conf.config_1 = 95;
    Classroom<conf> myClassroom;// doesn't work
}

It says: error: the value of 'conf' is not usable in a constant expression.

What am I missing?

like image 586
zku11126 Avatar asked Aug 26 '17 19:08

zku11126


People also ask

Which of the following can be passed to function template as an argument?

Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument.

How do you use template arguments in C++?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Can there be more than one arguments to templates?

As seen in the above cited example, we can use more than one parameter for a template in C++.


1 Answers

You can do that with some limitations. The way you are trying to do it isn't valid. It's a matter of storage.

If you need more than one configuration around, you can define it as a static member of a class template or define a global array of Configurations:

struct Configuration {
    int config_1;
};

template<int>
struct Accessor {
    static Configuration configuration;
};

template<int N>
Configuration Accessor<N>::configuration;

template<Configuration &conf>
class Classroom {
    int doSomething(int n){
        return n + conf.config_1;
    }
};

int main() {
    Accessor<1>::configuration.config_1 = 95;
    Classroom<Accessor<1>::configuration> myClassroom;
    (void)myClassroom;
}

If you can stick with a single instance, you can even put it in the global scope and use it instead:

struct Configuration {
    int config_1;
};

Configuration conf;

template<Configuration &conf>
struct Classroom {
    int doSomething(int n){
        return n + conf.config_1;
    }
};

int main() {
    conf.config_1 = 95;
    Classroom<conf> myClassroom;
    myClassroom.doSomething(42);
}

Other solutions are possible, but I'm sure you got the idea.


See the examples up and running on wandbox.

like image 145
skypjack Avatar answered Oct 06 '22 00:10

skypjack