Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Reference/pointer to member variable as template parameter

To start, I have something like this:

class Test {
    std::vector<int> a, b;
    void caller(...) { callee(...); }
    void callee(...) { /* Do stuff with 'a' */ }
}

What I wanted is to have a function that does exactly the same as callee but for vector b. To do this there are two obvious solutions:

  • Pass vector a or b as argument. However, callee is a recursive function that can go for hundreds of calls, and passing the vectors as arguments would just be unnecessary overhead.
  • Copy the function callee and use vector b, which would be the best alternative, despite the fact that callee is quite a long function and I would have a lot of duplicate code.

Out of curiosity, I went looking for the templates part and I noticed that can be used for

lvalue reference type

pointer type

pointer to member type

So I tried to do this:

class Test {
    std::vector<int> a, b;
    void caller(...) { callee<a>(...); }
    template <std::vector<int> &x> void callee(...) { /* Do stuff with 'x' */ }
}

but I get

error: use of ‘this’ in a constant expression

Is there any way to achieve this either with a reference or a pointer?

By the way, what I want can be seen as a function-scoped #define

like image 295
gmardau Avatar asked Nov 03 '16 12:11

gmardau


People also ask

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

How do you pass a variable by reference?

Pass-by-reference means to pass the reference of an argument in the calling function to the corresponding formal parameter of the called function. The called function can modify the value of the argument by using its reference passed in. The following example shows how arguments are passed by reference.

Can template type be a pointer?

A template has only one type, but a specialization is needed for pointer, reference, pointer to member, or function pointer types. The specialization itself is still a template on the type pointed to or referenced.

Can a template be a template parameter?

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.)


2 Answers

Arrays and even tuples, but no love for good old pointers-to-members ?

class Test {
    std::vector<int> a, b;

    void caller(/*...*/) { callee<&Test::a>(/*...*/); }

    template <std::vector<int> Test::*vec>
    void callee(/*...*/) { /* Do stuff with `(this->*vec)` */ }
};
like image 110
Quentin Avatar answered Sep 20 '22 03:09

Quentin


You cannot use a reference to a data member as a template argument: templates are compile-time, and the value of this is not known until runtime. In other words, you'd need a separate instantiation (separate binary code) for each runtime object of type Test.

What you can do is replace a and b with an array, and templatise callee by index into this array:

class Test {
    std::array<std::vector<int>, 2> ab;
    void caller(...) { callee<0>(...); }
    template <size_t idx>
    void callee(...) { /* Do stuff with 'ab[idx]' */ }
}

This way, you get only two instantiations of callee (one for 0 and one for 1), with the indexing done (or at least doable) at compile time.

like image 35
Angew is no longer proud of SO Avatar answered Sep 21 '22 03:09

Angew is no longer proud of SO