Search code examples
c++classtemplatestype-deduction

deduce member variable type


Edited: I forgot that the callback "captures" the this pointer of outer.

I am trying to initialize some class and its member.

The class is not templated.

It's member is templated. It takes a "function-type" by template for a call-back from the encapsulating class. (I can't use std::function as this is time-critical code.)

Furthermore, I would like that the compiler will deduce the template type for the call-back object(given to the member.)

the code would look something like this (assume all the boiler-plate exists):

template<typename func_t>
class inner : public inner_abstract_base
{
public:
    func_t m_cb;
    inner(func_t cb):m_cb(cb){}
};

class outer
{
    Int member_fun(int);
public:
    /*********first try****************/
    // inner member{[this]{return this->member_fun(123);}}

    /*********second try***************/
    // inner member;
    // outer():member([this]{return this->member_fun(321);})
    // {}

    /*********third try****************/
    // auto lamb = [this]{return this->member_fun(987);};
    //This or in the constructor initialization list
    // inner<decltype(lamb)> member{lamb};

    /*********fourth try***************/
    // friend int func();
    // inner<decltype(func)> member{func};

    /*********fifth try***************/
    // std::unique_ptr<inner_abstract_base> member_p;
    // outer():member_p([]{return 666;})
    // {}

    /*********sixth try***************/
    // inner<decltype(some_free_func)> member{some_free_func};

};

first try

I don't know for sure why it doesn't work. I'm guessing that in this type of initialization (braced in class definition) the compiler doesn't guess the template type. Maybe because it uses aggregate initialization(true?, and if so, why doesn't aggregate initialization support Template type deduction)

second try

This doesn't work because at the definition the template argument is not given. Only at the constructor it is called (at run-time) so template type deduction can't take place.

third try

non-static members can't be declared with auto (why??) - so the member lamb can't be initialized in the first place.

fourth try

I don't like this approach as it goes a bit further than the original design, but nonetheless - It doesn't work for some reason I can't understand.

fifth try

This is going overboard. I think this one doesn't work because I don't use it right. Probably because I didn't cast it to the son type for allocation...(How?). And maybe type deduction doesn't apply to that apparatus with the pointer even with "correct" usage.

sixth try

Just for fun - free fun! doesn't work for the same reason the friend function doesn't work(reasonable).

bottom line

How can you solve this fiasco with/without capturing the this pointer?

How can you let the compiler deduce the types of member variables?

Or more specifically in case given?

*I'm sorry for the back and forth with the editing...


Solution

  • deduce member variable type

    Is not possible in C++. Member variable types are not deduced.


    1. I don't know for sure why it doesn't work.

    First doesn't work because you didn't specify the template argument of the type of the member, and those cannot be deduced.

    ... Maybe because it uses aggregate initialization

    It does not.

    1. non-static members can't be declared with auto (why??)

    Because auto requires type deduction and types of member variables are not deduced.

    1. It doesn't work for some reason I can't understand.

    One reason it cannot work is because you attempt to specify a function type as the template argument and the inner class cannot have a member variable of a function type. It appears to fail before that due to name lookup problem.

    1. I think this one doesn't work because I don't use it right.

    You attempt to initialise a unique pointer with a lambda argument. Unique pointer simply doesn't have constructor accepting such argument.


    How can you solve this fiasco?

    One approach: Don't attempt to define a member variable. Use a member function for example:

    constexpr auto member_fun()
    {
        return inner{[]{return 123;}};
    }
    

    Since your lambda doesn't have internal state, a function pointer would also work:

    using fun = int();
    inner<fun*> member{[]{return 123;}};
    

    This may be harder to optimise than the function alternative since it's often not easy to prove that the function pointer wasn't changed. And const members are problematic.