4

I have a class which has a variadic member function:

class class_name {
  template<ArgTypes.. args>
  some_return_type memberMethod(ArgTypes... args) {
    //stuff...
  }
}

I need to force instantiation of this method inside the class definition block. I loose the method name outside of the class definition block because the class is generated by a bunch of macros.

I try to force the instantiation by copying a pointer to a specialised member function (pseudo code):

template<typename Self, typename RetType, typename... ArgTypes>
struct force_instantation_imlp<Self, RetType, type_placeholder, type_placeholder<ArgTypes...>> {
    force_instantation_imlp() {
        using instate = RetType (Self::*)(ArgTypes...);
        instate force = &Self::memberMethod<ArgTypes...>;        
    }
};


class class_name {
  template<ArgTypes.. args>
  some_return_type memberMethod(ArgTypes... args) {
    //stuff...
  }

  force_instantation_imlp<class_name, some_return_type, rest_of_types_deduced_from_context> force_virtual_instantation;
}

type_placeholder is just a helper template to "freeze" parameter pack.

This unfortunately gives me a compile error

error: expected primary-expression before ‘...’ token instate force = &Self::memberMethod<ArgTypes...>;

I guess that this error results from teh fact that the member function is a variadic template.

Is there any way to force variadic template member function instantiation inside the class definition block?

Manu343726
  • 13,969
  • 4
  • 40
  • 75
Marcin
  • 897
  • 1
  • 7
  • 19
  • 1
    You could just use `auto` instead of `instate` : `auto force = &Self::memberMethod;`. That saves you from writing the `using` to define a type. – Nawaz Aug 21 '13 at 11:14
  • Have you tried leaving out the explicit template arguments in `instate force = &Self::memberMethod;`? – dyp Aug 21 '13 at 11:22
  • @Nawaz good point. I still didn't develop c++11 habits. Still the issue remains open. – Marcin Aug 21 '13 at 11:23
  • 4
    ... I think you're missing a `template`: `&Self::template memberMethod;` – dyp Aug 21 '13 at 11:30
  • @DyP: That seems to be *a* problem (at least *one* problem). Good catch! – Nawaz Aug 21 '13 at 11:35
  • @Dyp Yes, now the code compiles. Thank you. Still I end up wit a bizarre result; decltype(&class_name::memberMethod) produces a compile error "decltype cannot resolve address of overloaded function", so it seems that the member function still didn't get instantiationed. Any sugesstions? – Marcin Aug 21 '13 at 11:45
  • 2
    @Marcin The reason why `instate force = &Self::memberMethod;` works is that the compiler can select the overload based on the required type (type of `instate`) in that context. That of course isn't possible for `decltype`. So inside decltype you'd need either a cast or explicitly specify the overload (e.g. using explicit template arguments). This of course is useless as you could directly specify the function type w/o `decltype` if you can access those parameter types. – dyp Aug 21 '13 at 11:50
  • @Dyp You are right, I've check it as you suggested. Please post your comment as an answer so I can accept it. – Marcin Aug 21 '13 at 12:01

1 Answers1

2

(Repeating from my comments to the OP.)

The actual problem in the line instate force = &Self::memberMethod<ArgTypes...>; is a missing template keyword:

instate force = &Self::template memberMethod<ArgTypes...>;

See, e.g. Where and why do I have to put the “template” and “typename” keywords?

Actually, the explicit template arguments are not necessary here [over.over]/1:

A use of an overloaded function name without arguments is resolved in certain contexts to [...] a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context.

i.e., because instate defines the function type, the compiler is able to determine which overload (here: template specialization) to choose for the name Self::memberMethod.


There might be easier solutions to force instantiation of a function template, even inside the class definition. One that comes to my mind is to use a private typedef like using dummy = integral_constant<instate, &Self::memberMethod>; (or a static constexpr instate dummy = &Self::memberMethod;).

I'm quite, but not 100 % sure the typedef forces the instantiation of the member function template. The function template is instantiated when a definition of that function is required, and the ODR suggests this is the case here: "A function whose name appears as a potentially-evaluated expression is odr-used if it is the unique lookup result or the selected member of a set of overloaded functions" and "Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program"

Community
  • 1
  • 1
dyp
  • 38,334
  • 13
  • 112
  • 177