Using std::apply with variadic packs












10















I am trying to create a generic class that takes a pack of types, stores them in a tuple, and can apply a function over them.



What I tried so far is the following:



#include <tuple>
struct Base{
virtual void base_function() = 0;
};

template<typename ...T>
struct A : public Base{
std::tuple<T...> as;
A(T... pack):as(pack...){};
void base_function(){
std::apply((auto t){t.base_function();}, as);
}
};

struct B : public Base{
void base_function(){};
};


struct C : public Base{
void base_function(){};
};

struct D : A<B, C>{
D():A(B(),C()){};
};


I expected apply to be called on base_function from class B and C when calling base_function on D. But the compiler generates the following error:




error: no matching function for call to

'__invoke(A<T>::base_function() [with T = {B, C}]::<lambda(auto:1)>,
std::__tuple_element_t<0, std::tuple<B, C> >&,
std::__tuple_element_t<1, std::tuple<B, C> >&)
'











share|improve this question

























  • Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

    – Spencer
    9 hours ago
















10















I am trying to create a generic class that takes a pack of types, stores them in a tuple, and can apply a function over them.



What I tried so far is the following:



#include <tuple>
struct Base{
virtual void base_function() = 0;
};

template<typename ...T>
struct A : public Base{
std::tuple<T...> as;
A(T... pack):as(pack...){};
void base_function(){
std::apply((auto t){t.base_function();}, as);
}
};

struct B : public Base{
void base_function(){};
};


struct C : public Base{
void base_function(){};
};

struct D : A<B, C>{
D():A(B(),C()){};
};


I expected apply to be called on base_function from class B and C when calling base_function on D. But the compiler generates the following error:




error: no matching function for call to

'__invoke(A<T>::base_function() [with T = {B, C}]::<lambda(auto:1)>,
std::__tuple_element_t<0, std::tuple<B, C> >&,
std::__tuple_element_t<1, std::tuple<B, C> >&)
'











share|improve this question

























  • Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

    – Spencer
    9 hours ago














10












10








10


1






I am trying to create a generic class that takes a pack of types, stores them in a tuple, and can apply a function over them.



What I tried so far is the following:



#include <tuple>
struct Base{
virtual void base_function() = 0;
};

template<typename ...T>
struct A : public Base{
std::tuple<T...> as;
A(T... pack):as(pack...){};
void base_function(){
std::apply((auto t){t.base_function();}, as);
}
};

struct B : public Base{
void base_function(){};
};


struct C : public Base{
void base_function(){};
};

struct D : A<B, C>{
D():A(B(),C()){};
};


I expected apply to be called on base_function from class B and C when calling base_function on D. But the compiler generates the following error:




error: no matching function for call to

'__invoke(A<T>::base_function() [with T = {B, C}]::<lambda(auto:1)>,
std::__tuple_element_t<0, std::tuple<B, C> >&,
std::__tuple_element_t<1, std::tuple<B, C> >&)
'











share|improve this question
















I am trying to create a generic class that takes a pack of types, stores them in a tuple, and can apply a function over them.



What I tried so far is the following:



#include <tuple>
struct Base{
virtual void base_function() = 0;
};

template<typename ...T>
struct A : public Base{
std::tuple<T...> as;
A(T... pack):as(pack...){};
void base_function(){
std::apply((auto t){t.base_function();}, as);
}
};

struct B : public Base{
void base_function(){};
};


struct C : public Base{
void base_function(){};
};

struct D : A<B, C>{
D():A(B(),C()){};
};


I expected apply to be called on base_function from class B and C when calling base_function on D. But the compiler generates the following error:




error: no matching function for call to

'__invoke(A<T>::base_function() [with T = {B, C}]::<lambda(auto:1)>,
std::__tuple_element_t<0, std::tuple<B, C> >&,
std::__tuple_element_t<1, std::tuple<B, C> >&)
'








c++ templates c++17 stdapply






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 6 hours ago









Cody Gray

193k35377465




193k35377465










asked 11 hours ago









sqrtrootsqrtroot

656




656













  • Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

    – Spencer
    9 hours ago



















  • Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

    – Spencer
    9 hours ago

















Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

– Spencer
9 hours ago





Just so you know, the Base and D classes (and any inheritance from Base) aren't necessary for a minimal example. Your problem manifests itself the same way (and @Jarod42's solution works the same way) even without them.

– Spencer
9 hours ago












2 Answers
2






active

oldest

votes


















16














First parameter of std::apply should be a functor with same arity that number of elements of the tuple, so variadic in your case:



template <typename ...Ts>
struct A : public Base{
std::tuple<Ts...> as;
A(Ts... pack) : as(pack...){}

void base_function(){
std::apply((auto&... ts){(ts.base_function(), ...);}, as);
}
};





share|improve this answer


























  • Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

    – sqrtroot
    11 hours ago






  • 5





    Look at fold expression.

    – Jarod42
    11 hours ago











  • This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

    – Spencer
    9 hours ago



















4














std::apply is not doing what you think. It is for a passing a tuple of parameters to a function (Callable type). In other words, the tuple itself doesn't have a function called base_function. see https://en.cppreference.com/w/cpp/utility/apply






share|improve this answer



















  • 2





    I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

    – Barry
    9 hours ago













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54631547%2fusing-stdapply-with-variadic-packs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









16














First parameter of std::apply should be a functor with same arity that number of elements of the tuple, so variadic in your case:



template <typename ...Ts>
struct A : public Base{
std::tuple<Ts...> as;
A(Ts... pack) : as(pack...){}

void base_function(){
std::apply((auto&... ts){(ts.base_function(), ...);}, as);
}
};





share|improve this answer


























  • Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

    – sqrtroot
    11 hours ago






  • 5





    Look at fold expression.

    – Jarod42
    11 hours ago











  • This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

    – Spencer
    9 hours ago
















16














First parameter of std::apply should be a functor with same arity that number of elements of the tuple, so variadic in your case:



template <typename ...Ts>
struct A : public Base{
std::tuple<Ts...> as;
A(Ts... pack) : as(pack...){}

void base_function(){
std::apply((auto&... ts){(ts.base_function(), ...);}, as);
}
};





share|improve this answer


























  • Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

    – sqrtroot
    11 hours ago






  • 5





    Look at fold expression.

    – Jarod42
    11 hours ago











  • This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

    – Spencer
    9 hours ago














16












16








16







First parameter of std::apply should be a functor with same arity that number of elements of the tuple, so variadic in your case:



template <typename ...Ts>
struct A : public Base{
std::tuple<Ts...> as;
A(Ts... pack) : as(pack...){}

void base_function(){
std::apply((auto&... ts){(ts.base_function(), ...);}, as);
}
};





share|improve this answer















First parameter of std::apply should be a functor with same arity that number of elements of the tuple, so variadic in your case:



template <typename ...Ts>
struct A : public Base{
std::tuple<Ts...> as;
A(Ts... pack) : as(pack...){}

void base_function(){
std::apply((auto&... ts){(ts.base_function(), ...);}, as);
}
};






share|improve this answer














share|improve this answer



share|improve this answer








edited 11 hours ago

























answered 11 hours ago









Jarod42Jarod42

116k12102184




116k12102184













  • Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

    – sqrtroot
    11 hours ago






  • 5





    Look at fold expression.

    – Jarod42
    11 hours ago











  • This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

    – Spencer
    9 hours ago



















  • Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

    – sqrtroot
    11 hours ago






  • 5





    Look at fold expression.

    – Jarod42
    11 hours ago











  • This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

    – Spencer
    9 hours ago

















Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

– sqrtroot
11 hours ago





Never seen the syntax used in the lambda, could you explain a bit more what it's actually doing. How does the compiler know what to do on the parameter pack ts?

– sqrtroot
11 hours ago




5




5





Look at fold expression.

– Jarod42
11 hours ago





Look at fold expression.

– Jarod42
11 hours ago













This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

– Spencer
9 hours ago





This is great, but you might want to add an explanation as to why std::apply doesn't work the way OP thought it did.

– Spencer
9 hours ago













4














std::apply is not doing what you think. It is for a passing a tuple of parameters to a function (Callable type). In other words, the tuple itself doesn't have a function called base_function. see https://en.cppreference.com/w/cpp/utility/apply






share|improve this answer



















  • 2





    I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

    – Barry
    9 hours ago


















4














std::apply is not doing what you think. It is for a passing a tuple of parameters to a function (Callable type). In other words, the tuple itself doesn't have a function called base_function. see https://en.cppreference.com/w/cpp/utility/apply






share|improve this answer



















  • 2





    I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

    – Barry
    9 hours ago
















4












4








4







std::apply is not doing what you think. It is for a passing a tuple of parameters to a function (Callable type). In other words, the tuple itself doesn't have a function called base_function. see https://en.cppreference.com/w/cpp/utility/apply






share|improve this answer













std::apply is not doing what you think. It is for a passing a tuple of parameters to a function (Callable type). In other words, the tuple itself doesn't have a function called base_function. see https://en.cppreference.com/w/cpp/utility/apply







share|improve this answer












share|improve this answer



share|improve this answer










answered 11 hours ago









darunedarune

1,407516




1,407516








  • 2





    I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

    – Barry
    9 hours ago
















  • 2





    I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

    – Barry
    9 hours ago










2




2





I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

– Barry
9 hours ago







I'd interpret OP's confusing as thinking apply takes a unary function and applies it to each element in the tuple in turn, not as applying a unary function directly to the tuple (which would be pointless, as you could just... do it already).

– Barry
9 hours ago




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54631547%2fusing-stdapply-with-variadic-packs%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Aikido

Tivadar Csontváry Kosztka

Metroo de Marsejlo