Is there any way in C++ to refer to a function template while neither calling it nor supplying its template...
Here's the code I would like to work:
template <class T> void Foo(T&& param);
template <class F> void CallMe(F&& func)
{
func(42);
}
int main()
{
CallMe(Foo);
}
The compiler chokes when it tries to instantiate CallMe
because it doesn't know what I mean by Foo
. It works if I write Foo<int>
of course, but I'd like to avoid that because in the real code the template parameters can be complex.
My current workaround is to use callable objects instead of free functions. For example:
class Foo
{
public:
template <class T> void operator()(T&&);
};
This works fine, but I'm sure it will confuse users of my library. Is there some template magic I can use to make the first version work?
c++ templates c++17
add a comment |
Here's the code I would like to work:
template <class T> void Foo(T&& param);
template <class F> void CallMe(F&& func)
{
func(42);
}
int main()
{
CallMe(Foo);
}
The compiler chokes when it tries to instantiate CallMe
because it doesn't know what I mean by Foo
. It works if I write Foo<int>
of course, but I'd like to avoid that because in the real code the template parameters can be complex.
My current workaround is to use callable objects instead of free functions. For example:
class Foo
{
public:
template <class T> void operator()(T&&);
};
This works fine, but I'm sure it will confuse users of my library. Is there some template magic I can use to make the first version work?
c++ templates c++17
3
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call tofunc
and deduce that it needs to instantiateFoo<int>
. I'm wondering if there's some way I could trick it into doing that.
– Peter Ruderman
Oct 6 '18 at 5:09
1
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
What do you expect shouldCallMe()
do, if neitherCallMe()
norFoo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.
– Scheff
Oct 6 '18 at 5:39
1
@PeterRuderman - your "workaround" is the solution in this case (assuming yourmain()
doesCallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement inmain()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).
– Peter
Oct 6 '18 at 5:58
add a comment |
Here's the code I would like to work:
template <class T> void Foo(T&& param);
template <class F> void CallMe(F&& func)
{
func(42);
}
int main()
{
CallMe(Foo);
}
The compiler chokes when it tries to instantiate CallMe
because it doesn't know what I mean by Foo
. It works if I write Foo<int>
of course, but I'd like to avoid that because in the real code the template parameters can be complex.
My current workaround is to use callable objects instead of free functions. For example:
class Foo
{
public:
template <class T> void operator()(T&&);
};
This works fine, but I'm sure it will confuse users of my library. Is there some template magic I can use to make the first version work?
c++ templates c++17
Here's the code I would like to work:
template <class T> void Foo(T&& param);
template <class F> void CallMe(F&& func)
{
func(42);
}
int main()
{
CallMe(Foo);
}
The compiler chokes when it tries to instantiate CallMe
because it doesn't know what I mean by Foo
. It works if I write Foo<int>
of course, but I'd like to avoid that because in the real code the template parameters can be complex.
My current workaround is to use callable objects instead of free functions. For example:
class Foo
{
public:
template <class T> void operator()(T&&);
};
This works fine, but I'm sure it will confuse users of my library. Is there some template magic I can use to make the first version work?
c++ templates c++17
c++ templates c++17
edited Nov 19 '18 at 17:00
asked Oct 6 '18 at 4:50


Peter Ruderman
10.1k2352
10.1k2352
3
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call tofunc
and deduce that it needs to instantiateFoo<int>
. I'm wondering if there's some way I could trick it into doing that.
– Peter Ruderman
Oct 6 '18 at 5:09
1
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
What do you expect shouldCallMe()
do, if neitherCallMe()
norFoo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.
– Scheff
Oct 6 '18 at 5:39
1
@PeterRuderman - your "workaround" is the solution in this case (assuming yourmain()
doesCallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement inmain()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).
– Peter
Oct 6 '18 at 5:58
add a comment |
3
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call tofunc
and deduce that it needs to instantiateFoo<int>
. I'm wondering if there's some way I could trick it into doing that.
– Peter Ruderman
Oct 6 '18 at 5:09
1
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
What do you expect shouldCallMe()
do, if neitherCallMe()
norFoo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.
– Scheff
Oct 6 '18 at 5:39
1
@PeterRuderman - your "workaround" is the solution in this case (assuming yourmain()
doesCallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement inmain()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).
– Peter
Oct 6 '18 at 5:58
3
3
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call to
func
and deduce that it needs to instantiate Foo<int>
. I'm wondering if there's some way I could trick it into doing that.– Peter Ruderman
Oct 6 '18 at 5:09
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call to
func
and deduce that it needs to instantiate Foo<int>
. I'm wondering if there's some way I could trick it into doing that.– Peter Ruderman
Oct 6 '18 at 5:09
1
1
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
What do you expect should
CallMe()
do, if neither CallMe()
nor Foo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.– Scheff
Oct 6 '18 at 5:39
What do you expect should
CallMe()
do, if neither CallMe()
nor Foo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.– Scheff
Oct 6 '18 at 5:39
1
1
@PeterRuderman - your "workaround" is the solution in this case (assuming your
main()
does CallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement in main()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).– Peter
Oct 6 '18 at 5:58
@PeterRuderman - your "workaround" is the solution in this case (assuming your
main()
does CallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement in main()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).– Peter
Oct 6 '18 at 5:58
add a comment |
4 Answers
4
active
oldest
votes
Is there some template magic I can use to make the first version work?
I wish. And I hope someday. There have been several proposals in this area (e.g. P0119 and P0834). Until then, the best you can do is write a lifting macro to turn your name into a function object that calls that name:
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#define LIFT(name) [&](auto&&... args)
noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...))
{ return name(FWD(args)...); }
This lets you write:
CallMe(LIFT(Foo));
which otherwise does what you want.
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is[&]
the right thing to do inLIFT
? Seems ... dangerous to hide an implicit capture like that.
– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me writeLIFT(obj.foo)
in a way that works and doesn't copyobj
. I don't really use this in places where I would need the copy.
– Barry
Oct 6 '18 at 23:40
add a comment |
It is possible to make something that somewhat resembles the code in the question, but not exactly.
A function call:
int main()
{
CallMe(Foo);
}
expects an object as a parameter. The object can be a function pointer, a class instance, a lambda, or something similar. It can't be an uninstantiated template function, since it is not an object. Only an instantiated function is an object.
As the original question states, using function-like objects is a work-around, and assumes that the following is too confusing for some users:
class Foo
{
public:
template <class T> void operator()(T&&);
};
Instead of that, it is possible to use a generic lambda, which is basically the same, but without all the boiler plate. A generic lambda looks almost like a regular function:
auto Foo = (auto x)
{
std::cout << x << 'n';
};
int main()
{
CallMe(Foo);
}
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
add a comment |
Is there some template magic I can use to make the first version work?
No.
The name of a function template don’t name a function type but a family of them. If it were possible, and the type of func
would be deduced from Foo
the type of T
will remain non-deduced which is needed in order to instantiate the Foo
.
add a comment |
#define RETURNS(...)
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...)
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
then
CallMe(OVERLOADS_OF(Foo));
creates a function object that represents the overloads of the name Foo
, which include the functions produced by your template function named Foo
.
RETURNS
is also useful in other contexts. @Barry has a proposal to make RETURNS(X)
be similar to => X
, at least for lambdas.
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%2f52675813%2fis-there-any-way-in-c-to-refer-to-a-function-template-while-neither-calling-it%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Is there some template magic I can use to make the first version work?
I wish. And I hope someday. There have been several proposals in this area (e.g. P0119 and P0834). Until then, the best you can do is write a lifting macro to turn your name into a function object that calls that name:
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#define LIFT(name) [&](auto&&... args)
noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...))
{ return name(FWD(args)...); }
This lets you write:
CallMe(LIFT(Foo));
which otherwise does what you want.
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is[&]
the right thing to do inLIFT
? Seems ... dangerous to hide an implicit capture like that.
– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me writeLIFT(obj.foo)
in a way that works and doesn't copyobj
. I don't really use this in places where I would need the copy.
– Barry
Oct 6 '18 at 23:40
add a comment |
Is there some template magic I can use to make the first version work?
I wish. And I hope someday. There have been several proposals in this area (e.g. P0119 and P0834). Until then, the best you can do is write a lifting macro to turn your name into a function object that calls that name:
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#define LIFT(name) [&](auto&&... args)
noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...))
{ return name(FWD(args)...); }
This lets you write:
CallMe(LIFT(Foo));
which otherwise does what you want.
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is[&]
the right thing to do inLIFT
? Seems ... dangerous to hide an implicit capture like that.
– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me writeLIFT(obj.foo)
in a way that works and doesn't copyobj
. I don't really use this in places where I would need the copy.
– Barry
Oct 6 '18 at 23:40
add a comment |
Is there some template magic I can use to make the first version work?
I wish. And I hope someday. There have been several proposals in this area (e.g. P0119 and P0834). Until then, the best you can do is write a lifting macro to turn your name into a function object that calls that name:
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#define LIFT(name) [&](auto&&... args)
noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...))
{ return name(FWD(args)...); }
This lets you write:
CallMe(LIFT(Foo));
which otherwise does what you want.
Is there some template magic I can use to make the first version work?
I wish. And I hope someday. There have been several proposals in this area (e.g. P0119 and P0834). Until then, the best you can do is write a lifting macro to turn your name into a function object that calls that name:
#define FWD(...) std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
#define LIFT(name) [&](auto&&... args)
noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...))
{ return name(FWD(args)...); }
This lets you write:
CallMe(LIFT(Foo));
which otherwise does what you want.
answered Oct 6 '18 at 13:38


Barry
177k18304561
177k18304561
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is[&]
the right thing to do inLIFT
? Seems ... dangerous to hide an implicit capture like that.
– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me writeLIFT(obj.foo)
in a way that works and doesn't copyobj
. I don't really use this in places where I would need the copy.
– Barry
Oct 6 '18 at 23:40
add a comment |
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is[&]
the right thing to do inLIFT
? Seems ... dangerous to hide an implicit capture like that.
– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me writeLIFT(obj.foo)
in a way that works and doesn't copyobj
. I don't really use this in places where I would need the copy.
– Barry
Oct 6 '18 at 23:40
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Thanks for the answer and the links. Those are an interesting read.
– Peter Ruderman
Oct 6 '18 at 14:57
Is
[&]
the right thing to do in LIFT
? Seems ... dangerous to hide an implicit capture like that.– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
Is
[&]
the right thing to do in LIFT
? Seems ... dangerous to hide an implicit capture like that.– Yakk - Adam Nevraumont
Oct 6 '18 at 23:25
@Yakk-AdamNevraumont I dunno. Let's me write
LIFT(obj.foo)
in a way that works and doesn't copy obj
. I don't really use this in places where I would need the copy.– Barry
Oct 6 '18 at 23:40
@Yakk-AdamNevraumont I dunno. Let's me write
LIFT(obj.foo)
in a way that works and doesn't copy obj
. I don't really use this in places where I would need the copy.– Barry
Oct 6 '18 at 23:40
add a comment |
It is possible to make something that somewhat resembles the code in the question, but not exactly.
A function call:
int main()
{
CallMe(Foo);
}
expects an object as a parameter. The object can be a function pointer, a class instance, a lambda, or something similar. It can't be an uninstantiated template function, since it is not an object. Only an instantiated function is an object.
As the original question states, using function-like objects is a work-around, and assumes that the following is too confusing for some users:
class Foo
{
public:
template <class T> void operator()(T&&);
};
Instead of that, it is possible to use a generic lambda, which is basically the same, but without all the boiler plate. A generic lambda looks almost like a regular function:
auto Foo = (auto x)
{
std::cout << x << 'n';
};
int main()
{
CallMe(Foo);
}
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
add a comment |
It is possible to make something that somewhat resembles the code in the question, but not exactly.
A function call:
int main()
{
CallMe(Foo);
}
expects an object as a parameter. The object can be a function pointer, a class instance, a lambda, or something similar. It can't be an uninstantiated template function, since it is not an object. Only an instantiated function is an object.
As the original question states, using function-like objects is a work-around, and assumes that the following is too confusing for some users:
class Foo
{
public:
template <class T> void operator()(T&&);
};
Instead of that, it is possible to use a generic lambda, which is basically the same, but without all the boiler plate. A generic lambda looks almost like a regular function:
auto Foo = (auto x)
{
std::cout << x << 'n';
};
int main()
{
CallMe(Foo);
}
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
add a comment |
It is possible to make something that somewhat resembles the code in the question, but not exactly.
A function call:
int main()
{
CallMe(Foo);
}
expects an object as a parameter. The object can be a function pointer, a class instance, a lambda, or something similar. It can't be an uninstantiated template function, since it is not an object. Only an instantiated function is an object.
As the original question states, using function-like objects is a work-around, and assumes that the following is too confusing for some users:
class Foo
{
public:
template <class T> void operator()(T&&);
};
Instead of that, it is possible to use a generic lambda, which is basically the same, but without all the boiler plate. A generic lambda looks almost like a regular function:
auto Foo = (auto x)
{
std::cout << x << 'n';
};
int main()
{
CallMe(Foo);
}
It is possible to make something that somewhat resembles the code in the question, but not exactly.
A function call:
int main()
{
CallMe(Foo);
}
expects an object as a parameter. The object can be a function pointer, a class instance, a lambda, or something similar. It can't be an uninstantiated template function, since it is not an object. Only an instantiated function is an object.
As the original question states, using function-like objects is a work-around, and assumes that the following is too confusing for some users:
class Foo
{
public:
template <class T> void operator()(T&&);
};
Instead of that, it is possible to use a generic lambda, which is basically the same, but without all the boiler plate. A generic lambda looks almost like a regular function:
auto Foo = (auto x)
{
std::cout << x << 'n';
};
int main()
{
CallMe(Foo);
}
answered Oct 6 '18 at 10:49


Michael Veksler
2,3771415
2,3771415
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
add a comment |
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
Interesting idea. I'm not sure if this works for me or not. I'll play around with it.
– Peter Ruderman
Oct 6 '18 at 14:38
add a comment |
Is there some template magic I can use to make the first version work?
No.
The name of a function template don’t name a function type but a family of them. If it were possible, and the type of func
would be deduced from Foo
the type of T
will remain non-deduced which is needed in order to instantiate the Foo
.
add a comment |
Is there some template magic I can use to make the first version work?
No.
The name of a function template don’t name a function type but a family of them. If it were possible, and the type of func
would be deduced from Foo
the type of T
will remain non-deduced which is needed in order to instantiate the Foo
.
add a comment |
Is there some template magic I can use to make the first version work?
No.
The name of a function template don’t name a function type but a family of them. If it were possible, and the type of func
would be deduced from Foo
the type of T
will remain non-deduced which is needed in order to instantiate the Foo
.
Is there some template magic I can use to make the first version work?
No.
The name of a function template don’t name a function type but a family of them. If it were possible, and the type of func
would be deduced from Foo
the type of T
will remain non-deduced which is needed in order to instantiate the Foo
.
answered Oct 6 '18 at 8:06
Jans
8,51822635
8,51822635
add a comment |
add a comment |
#define RETURNS(...)
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...)
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
then
CallMe(OVERLOADS_OF(Foo));
creates a function object that represents the overloads of the name Foo
, which include the functions produced by your template function named Foo
.
RETURNS
is also useful in other contexts. @Barry has a proposal to make RETURNS(X)
be similar to => X
, at least for lambdas.
add a comment |
#define RETURNS(...)
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...)
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
then
CallMe(OVERLOADS_OF(Foo));
creates a function object that represents the overloads of the name Foo
, which include the functions produced by your template function named Foo
.
RETURNS
is also useful in other contexts. @Barry has a proposal to make RETURNS(X)
be similar to => X
, at least for lambdas.
add a comment |
#define RETURNS(...)
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...)
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
then
CallMe(OVERLOADS_OF(Foo));
creates a function object that represents the overloads of the name Foo
, which include the functions produced by your template function named Foo
.
RETURNS
is also useful in other contexts. @Barry has a proposal to make RETURNS(X)
be similar to => X
, at least for lambdas.
#define RETURNS(...)
noexcept(noexcept(__VA_ARGS__))
-> decltype(__VA_ARGS__)
{ return __VA_ARGS__; }
#define OVERLOADS_OF(...)
(auto&&...args)
RETURNS( __VA_ARGS__( decltype(args)(args)... ) )
then
CallMe(OVERLOADS_OF(Foo));
creates a function object that represents the overloads of the name Foo
, which include the functions produced by your template function named Foo
.
RETURNS
is also useful in other contexts. @Barry has a proposal to make RETURNS(X)
be similar to => X
, at least for lambdas.
answered Oct 8 '18 at 4:00
Yakk - Adam Nevraumont
182k19189374
182k19189374
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f52675813%2fis-there-any-way-in-c-to-refer-to-a-function-template-while-neither-calling-it%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
3
template functions are recipes for creating functions. They aren't functions themselves. Since they are only recipes, there is no way to know which of an infinite possible number of instantiated functions one could refer to.
– doug
Oct 6 '18 at 5:02
This can work, in principle. In fact, functional languages like F# do work this way. If only the compiler would "hold off" a little bit, it could see my call to
func
and deduce that it needs to instantiateFoo<int>
. I'm wondering if there's some way I could trick it into doing that.– Peter Ruderman
Oct 6 '18 at 5:09
1
You can use the address of a template function as soon as you apply template arguments. This results effectively in the instancing of this template function. You can use the address of a template function in another template applying its template arguments. This results in instancing of this template function with the other template as soon as that is instanced. As already mentioned by @doug, without template arguments, it's not possible. Whatever F# or other functional languages do, this is not what happens in C++.
– Scheff
Oct 6 '18 at 5:34
What do you expect should
CallMe()
do, if neitherCallMe()
norFoo()
has a concrete type? Please, note that template functions may deduce its concrete type from a call with arguments of concrete types. (Again, this results in instancing of this template function.) However, this is not true for class templates.– Scheff
Oct 6 '18 at 5:39
1
@PeterRuderman - your "workaround" is the solution in this case (assuming your
main()
doesCallMe(Foo())
to pass an object, not a type). In C++, the call point (the statement inmain()
in your case) needs to provide all information needed so the compiler can deduce the type. The compiler does not "hold off" in the way you wish - doing so would interact badly with a bunch of other language features (e.g. separate compilation model, extern templates in C++11, etc).– Peter
Oct 6 '18 at 5:58