Using std::apply with variadic packs
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
add a comment |
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
Just so you know, theBaseandDclasses (and any inheritance fromBase) 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
add a comment |
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
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
c++ templates c++17 stdapply
edited 6 hours ago
Cody Gray♦
193k35377465
193k35377465
asked 11 hours ago
sqrtrootsqrtroot
656
656
Just so you know, theBaseandDclasses (and any inheritance fromBase) 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
add a comment |
Just so you know, theBaseandDclasses (and any inheritance fromBase) 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
add a comment |
2 Answers
2
active
oldest
votes
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);
}
};
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 packts?
– 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 whystd::applydoesn't work the way OP thought it did.
– Spencer
9 hours ago
add a comment |
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
2
I'd interpret OP's confusing as thinkingapplytakes 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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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);
}
};
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 packts?
– 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 whystd::applydoesn't work the way OP thought it did.
– Spencer
9 hours ago
add a comment |
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);
}
};
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 packts?
– 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 whystd::applydoesn't work the way OP thought it did.
– Spencer
9 hours ago
add a comment |
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);
}
};
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);
}
};
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 packts?
– 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 whystd::applydoesn't work the way OP thought it did.
– Spencer
9 hours ago
add a comment |
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 packts?
– 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 whystd::applydoesn'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
add a comment |
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
2
I'd interpret OP's confusing as thinkingapplytakes 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
add a comment |
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
2
I'd interpret OP's confusing as thinkingapplytakes 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
add a comment |
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
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
answered 11 hours ago
darunedarune
1,407516
1,407516
2
I'd interpret OP's confusing as thinkingapplytakes 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
add a comment |
2
I'd interpret OP's confusing as thinkingapplytakes 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
Just so you know, the
BaseandDclasses (and any inheritance fromBase) 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