samedi 17 juillet 2021

What's the difference between template deducted type and explicitly indicating the type

Context: Trying to create a class to unpack a tuple (used to store variadic template arguments). Inspired by this answer https://stackoverflow.com/a/24804339/11510510 I have something that does the job.

(I'm restricted to c++11 if not I would be using std::apply from C++17)

Problem: It only compiles when the object is created by using the specific type and not inside a template.

Target class to instantiate

    template<class C, class ...Args>
    struct APPLY_TUPLE{};
    
    template<class C, class ...Args>
    struct APPLY_TUPLE<C, std::tuple<Args...>>{
        // irrelevant code
    };

Class Instantiating the APPLY_TUPPLE

    template<typename C, typename R>
    struct TupledCall
    {     
        TupledCall(C& obj) : object{obj} {}
     
        R MethodTrigger(){
             // instantiate APPLY_TUPLE here with type of object        
        }

        C &object;
    };

/*Instantiation as*/
auto obj = Summator();
auto tupledCall = TupledCall<Summator, int>(obj);
tupledCall.MethodTrigger();

What compiles

R MethodTrigger(){
    tuple<int,int,int> list = make_tuple(1,5,4);

    auto tup = APPLY_TUPLE<Summator, args(list)>(object);
    return tup.delayed_call<int , &Summator::sum>(list);
}

R MethodTrigger(){
    tuple<int,int,int> list = make_tuple(1,5,4);
    
    Summator s = Summator();
    auto tup = APPLY_TUPLE<typename decay<decltype(s)>::type, args(list)>(object);
    return tup.delayed_call<int , &Summator::sum>(list);
}

What doesn't compile

R MethodTrigger(){
    tuple<int,int,int> list = make_tuple(1,5,4);

    auto tup = APPLY_TUPLE<C, args(list)>(object);
    return tup.delayed_call<int , &Summator::sum>(list);
}

R MethodTrigger(){
    tuple<int,int,int> list = make_tuple(1,5,4);
    
    auto tup = APPLY_TUPLE<typename decay<decltype(object)>::type, args(list)>(object);
    return tup.delayed_call<int , &Summator::sum>(list);
}

R MethodTrigger(){
    tuple<int,int,int> list = make_tuple(1,5,4);
    
    C sum = C(); // C should be deducted as Summator in this template
    auto tup = APPLY_TUPLE<typename decay<decltype(object)>::type, args(list)>(object);
    return tup.delayed_call<int , &Sumator::sum>(list);
}

What is the difference between them? Why it doesn't compile when trying to make the solution generic?

Compiler error

    <source>: In member function 'R TupledCall<C, R>::MethodTrigger()':
<source>:80:37: error: expected primary-expression before 'int'
   80 |             return tup.delayed_call<int , &Summator::sum>(list);
      |                                     ^~~
<source>:80:37: error: expected ';' before 'int'
<source>:80:41: error: expected unqualified-id before ',' token
   80 |             return tup.delayed_call<int , &Summator::sum>(list);
      |                                         ^
<source>:80:57: error: qualified-id in declaration before '>' token
   80 |             return tup.delayed_call<int , &Summator::sum>(list);

Aucun commentaire:

Enregistrer un commentaire