Is there any way in C++ to refer to a function template while neither calling it nor supplying its template...












2














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?










share|improve this question




















  • 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 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




    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






  • 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
















2














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?










share|improve this question




















  • 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 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




    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






  • 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














2












2








2


1





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?










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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




    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






  • 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














  • 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 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




    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






  • 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








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












4 Answers
4






active

oldest

votes


















4















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.






share|improve this answer





















  • 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












  • @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



















2














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);
}





share|improve this answer





















  • 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



















1















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.






share|improve this answer





























    0














    #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.






    share|improve this answer





















      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%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









      4















      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.






      share|improve this answer





















      • 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












      • @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
















      4















      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.






      share|improve this answer





















      • 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












      • @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














      4












      4








      4







      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.






      share|improve this answer













      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      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 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


















      • 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












      • @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
















      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













      2














      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);
      }





      share|improve this answer





















      • 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
















      2














      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);
      }





      share|improve this answer





















      • 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














      2












      2








      2






      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);
      }





      share|improve this answer












      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);
      }






      share|improve this answer












      share|improve this answer



      share|improve this answer










      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


















      • 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











      1















      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.






      share|improve this answer


























        1















        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.






        share|improve this answer
























          1












          1








          1







          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.






          share|improve this answer













          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Oct 6 '18 at 8:06









          Jans

          8,51822635




          8,51822635























              0














              #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.






              share|improve this answer


























                0














                #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.






                share|improve this answer
























                  0












                  0








                  0






                  #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.






                  share|improve this answer












                  #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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Oct 8 '18 at 4:00









                  Yakk - Adam Nevraumont

                  182k19189374




                  182k19189374






























                      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.





                      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.




                      draft saved


                      draft discarded














                      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





















































                      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

                      MongoDB - Not Authorized To Execute Command

                      How to fix TextFormField cause rebuild widget in Flutter

                      in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith