function template with a universal reference to a specific type
Hi, I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know. How can I write a function template, which has a parameter of the universal reference to a specific type? I can write a function template like this: template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; } And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this: int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); } In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that? Best, Irek
I don't know answer to your question but if you want to know about another generic C++ newsgroup then you can try this: <news://nntp.aioe.org/comp.lang.c++> It is very active but like any unmoderated newsgroups, you can expect the thread to drift away from the main question. Good luck and a very Happy & Prosperous New Year On 30/12/2018 15:04, Ireneusz Szcześniak via Boost-users wrote:
Hi,
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
How can I write a function template, which has a parameter of the universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
Best, Irek
Thank you for the advice! On 30.12.2018 17:16, Good Guy via Boost-users wrote:
I don't know answer to your question but if you want to know about another generic C++ newsgroup then you can try this:
<news://nntp.aioe.org/comp.lang.c++>
It is very active but like any unmoderated newsgroups, you can expect the thread to drift away from the main question.
Good luck and a very Happy & Prosperous New Year
On 30/12/2018 15:04, Ireneusz Szcześniak via Boost-users wrote:
Hi,
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
How can I write a function template, which has a parameter of the universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
Best, Irek
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
On Sun, 30 Dec 2018 at 17:05, Ireneusz Szcześniak via Boost-users < boost-users@lists.boost.org> wrote:
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
A better place would be https://www.reddit.com/r/cpp_questions/ [relatively informal] or https://stackoverflow.com/ [more formal, requirement for good formulation of your problem]. How can I write a function template, which has a parameter of the
universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
You have to read up on universal references [ https://en.cppreference.com/w/cpp/language/reference] as in the above a UR seems in-appropriate, as printing in general should [normally] not involve "consuming" [i.e. move] the value your printing. It's saves typing but "using namespace std;" will, once you get bigger projects, give you [potentially] grief, it's advisable to just type std:: everywhere. If there are really long [and several nested namespaces] you can just write a short-cut, like so namespace fs = std::filesystem; And so I can call this function with an expression of any value
category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
You can simply overload the <<-operator for the types you need. Like [just copied some code as an example]: template<typename Stream> [[ maybe_unused ]] Stream & operator << ( Stream & out_, const point2f & p_ ) noexcept { out_ << '<' << p_.x << ' ' << p_.y << '>'; return out_; } after which you can just write: point2f p { 1.2f, 5.6f }; std::cout << p << '\n'; The nice thing [of the above] is that it [your overload] will also work with other stream-types [https://en.cppreference.com/w/cpp/io]. degski -- *“If something cannot go on forever, it will stop" - Herbert Stein*
Hi degski, Thank you for your email, but you missed the point of my email. Please note that in the foo function I'm not using parameter t, so the use of the forwarding (universal) reference cannot be inappropriate. Best, Irek On 31.12.2018 07:09, degski wrote:
On Sun, 30 Dec 2018 at 17:05, Ireneusz Szcześniak via Boost-users <boost-users@lists.boost.org <mailto:boost-users@lists.boost.org>> wrote:
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
A better place would be https://www.reddit.com/r/cpp_questions/ [relatively informal] or https://stackoverflow.com/ [more formal, requirement for good formulation of your problem].
How can I write a function template, which has a parameter of the universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
You have to read up on universal references [https://en.cppreference.com/w/cpp/language/reference] as in the above a UR seems in-appropriate, as printing in general should [normally] not involve "consuming" [i.e. move] the value your printing. It's saves typing but "using namespace std;" will, once you get bigger projects, give you [potentially] grief, it's advisable to just type std:: everywhere. If there are really long [and several nested namespaces] you can just write a short-cut, like so
namespace fs = std::filesystem;
And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
You can simply overload the <<-operator for the types you need.
Like [just copied some code as an example]:
template<typename Stream> [[ maybe_unused ]] Stream & operator << ( Stream & out_, const point2f & p_ ) noexcept { out_ << '<' << p_.x << ' ' << p_.y << '>'; return out_; }
after which you can just write:
point2f p { 1.2f, 5.6f }; std::cout << p << '\n';
The nice thing [of the above] is that it [your overload] will also work with other stream-types [https://en.cppreference.com/w/cpp/io].
degski -- /*/*“*/If something cannot go on forever, it will stop" - Herbert Stein*/
On Mon, 31 Dec 2018 at 10:00, Ireneusz Szcześniak via Boost-users < boost-users@lists.boost.org> wrote:
Thank you for your email, but you missed the point of my email.
Possibly. Please note that in the foo function I'm not using parameter t, so the
use of the forwarding (universal) reference cannot be inappropriate.
I assumed __PRETTY_FUNCTION__ was doing something with t. If that is not doing something with t, what are you pretty printing then? Are you saying that you want to print something different depending upon the type [but unrelated to the value of t]? Overloading is still the [an] answer, though. It would be helpful if you state more clearly what you want to do and why you think you need a UR. This SO-question goes into some depth to explain the differences [it's more intricate than it seems, but once you got the hang of it in practice it's quite easy]. In the case of PODs [as in your examples], all this is rather moot, and you can just as well use value-semantics. template<typename Stream> [[ maybe_unused ]] Stream & operator << ( Stream & out_, const point2f & ) noexcept { out_ << "I'm using a type called point2f"; return out_; } A parameter that's not used does not have to have a name. degski -- *“If something cannot go on forever, it will stop" - Herbert Stein*
On 31.12.2018 10:20, degski wrote:
I assumed __PRETTY_FUNCTION__ was doing something with t. If that is not doing something with t, what are you pretty printing then? Are you saying that you want to print something different depending upon the type [but unrelated to the value of t]? Overloading is still the [an] answer, though. It would be helpful if you state more clearly what you want to do and why you think you need a UR. This SO-question goes into some depth to explain the differences [it's more intricate than it seems, but once you got the hang of it in practice it's quite easy]. In the case of PODs [as in your examples], all this is rather moot, and you can just as well use value-semantics.
I used __PRETTY_FUNCTION__ to make sure that the function is instantiated with the template argument deduced as I expected. I didn't use parameter t, because it was not relevant to the problem. I can provide function overloads or more function templates for various arguments the function could be called with: class A {}; void foo(A &a) {} void foo(const A &a) {} void foo(A &&a) {} and for templated types: template <typename T> class B {}; template<typename T> void foo(B<T> &a) {} template<typename T> void foo(const B<T> &a) {} template<typename T> void foo(B<T> &&a) {} But it would be more generic to provide a single function implementation, and that's my motivation. Best, Irek
Hi Irek, I am confused, because you wrote
I need to provide different implementations of foo for different types
and
it would be more generic to provide a single function implementation
which I find contradictory. Do you mean that you want to write a templated implementation once, and that implementation should call different function/methods/etc. depending on the templated type ? Regards, .Andrea
Hi Andrea, Yes, I need to provide different implementations of foo for different types, but a single function implementation for a given type. That implementation would be, most probably, a function template overload. Best, Irek On 31.12.2018 11:51, Andrea Bocci wrote:
Hi Irek, I am confused, because you wrote
I need to provide different implementations of foo for different types
and
it would be more generic to provide a single function implementation
which I find contradictory.
Do you mean that you want to write a templated implementation once, and that implementation should call different function/methods/etc. depending on the templated type ?
Regards, .Andrea
I think what you're asking is "how can I constrain a universal reference to be one primary type?" One way is to implement the general interface in terms of a specialised function object (this is my favourite). example: http://coliru.stacked-crooked.com/a/317cadb674e175b7 This is my favourite because it allows selection of specialisations based on pattern matching rather than explicit overloads. #include <type_traits> #include <iostream> template<class T> struct foo_op { template<class Prefix, class Arg> void operator()(Prefix&& p, Arg&& /* a */) const { p(); } }; template <typename T> auto foo(T &&t) { auto op = foo_op<std::decay_t<T>>(); return op([funcname = __PRETTY_FUNCTION__] { std::cout << "Primary: " << funcname << std::endl; }, std::forward<T>(t)); } // then specialise struct Bar {}; template<> struct foo_op<Bar> { template<class Prefix, class Arg> void operator()(Prefix&& /*p*/, Arg&& /*bar*/) const { std::cout << "It's a Bar\n"; } }; int main() { foo(6); // default case foo(Bar()); // bar case } On Sun, 30 Dec 2018 at 16:05, Ireneusz Szcześniak via Boost-users < boost-users@lists.boost.org> wrote:
Hi,
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
How can I write a function template, which has a parameter of the universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
Best, Irek _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Richard Hodges hodges.r@gmail.com office: +442032898513 home: +376841522 mobile: +376380212 (this will be *expensive* outside Andorra!) skype: madmongo facebook: hodges.r
Thank you, Richard! That's very interesting. The function template works as a dispatcher, so that we get T deduced. The specialization can be partial since it is implemented as a struct, and so your solution also works for templated types: template <typename T> struct Bar {}; template<typename T> struct foo_op<Bar<T>> { template<class Prefix, class Arg> void operator()(Prefix&& /*p*/, Arg&& /*bar*/) const { std::cout << "It's a Bar\n"; } }; Your solution is nifty, but also mind-boggling! Best, Irek On 31.12.2018 13:04, Richard Hodges via Boost-users wrote:
I think what you're asking is "how can I constrain a universal reference to be one primary type?"
One way is to implement the general interface in terms of a specialised function object (this is my favourite).
example:
http://coliru.stacked-crooked.com/a/317cadb674e175b7
This is my favourite because it allows selection of specialisations based on pattern matching rather than explicit overloads.
#include <type_traits> #include <iostream>
template<class T> struct foo_op { template<class Prefix, class Arg> void operator()(Prefix&& p, Arg&& /* a */) const { p(); } };
template <typename T> auto foo(T &&t) { auto op = foo_op<std::decay_t<T>>(); return op([funcname = __PRETTY_FUNCTION__] { std::cout << "Primary: " << funcname << std::endl; }, std::forward<T>(t)); }
// then specialise
struct Bar {};
template<> struct foo_op<Bar> { template<class Prefix, class Arg> void operator()(Prefix&& /*p*/, Arg&& /*bar*/) const { std::cout << "It's a Bar\n"; } };
int main() { foo(6); // default case foo(Bar()); // bar case }
On Sun, 30 Dec 2018 at 16:05, Ireneusz Szcześniak via Boost-users <boost-users@lists.boost.org <mailto:boost-users@lists.boost.org>> wrote:
Hi,
I'm writing to ask a C++ question, not specifically Boost-related, but this list is the best place I know.
How can I write a function template, which has a parameter of the universal reference to a specific type?
I can write a function template like this:
template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; }
And so I can call this function with an expression of any value category, and any type, cv-qualified or not, like this:
int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); }
In my code I need to provide different implementations of foo for different types (and these types are templated). How can I accomplish that?
Best, Irek _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org <mailto:Boost-users@lists.boost.org> https://lists.boost.org/mailman/listinfo.cgi/boost-users
-- Richard Hodges hodges.r@gmail.com <mailto:hodges.r@gmail.com> office: +442032898513 home: +376841522 mobile: +376380212 (this will be *expensive* outside Andorra!) skype: madmongo facebook: hodges.r
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users
I came up with a solution with a template requirement -- please see below. It works fine with non-templated types (type A below), but not with templated types (type B below). I would appreciate it if someone could help me get it work with templated types too. Best, Irek *********************************************************** http://coliru.stacked-crooked.com/a/6219c292938b4067 Compiled with: g++ -std=c++2a -fconcepts main.cc -o main *********************************************************** #include <iostream> #include <type_traits> using namespace std; template <typename T> void foo(T &&t) { // The primary template implementation. cout << "Primary: " << __PRETTY_FUNCTION__ << endl; } struct A { }; template <typename T> void foo(T &&t) requires is_same_v<decay_t<T>, A> { // Overload for A. cout << "Overload for A: " << __PRETTY_FUNCTION__ << endl; } template <typename T> struct B { }; template <typename T> void foo(T &&t) requires is_same_v<decay_t<T>, B> { // Overload for B. cout << "Overload for B: " << __PRETTY_FUNCTION__ << endl; } int main() { foo(1); int i = 1; foo(i); const int ci = 1; foo(ci); foo(A()); A a; foo(a); const A ca; foo(ca); foo(B<int>()); B<int> b; foo(b); const B<int> cb; foo(cb); }
participants (5)
-
Andrea Bocci
-
degski
-
Good Guy
-
Ireneusz Szcześniak
-
Richard Hodges