So I've got a templatized class and I want to overload the behavior of a function when I have specific type, say char. For all other types, let them do their own thing. However, c++ won't let me overload the function.
Why can't I overload this function? I really really do not want to do template specialization, because then I've got duplicate the entire class.
Here is a toy example demonstrating the problem: http://codepad.org/eTgLG932
The same code posted here for your reading pleasure:
#include <iostream>
#include <cstdlib>
#include <string>
struct Bar
{
std::string blah() { return "blah"; }
};
template <typename T>
struct Foo
{
public:
std::string doX()
{
return m_getY(my_t);
}
private:
std::string m_getY(char* p_msg)
{
return std::string(p_msg);
}
std::string m_getY(T* p_msg)
{
return p_msg->blah();
}
T my_t;
};
int main(int, char**)
{
Foo<char> x;
Foo<Bar> y;
std::cout << "x " << x.doX() << std::endl;
return EXIT_SUCCESS;
}
Thank you everyone for your suggestions. Two valid solutions have been presented. I can either specialize the doX method, or specialize m_getY() method.
At the end of the day I prefer to keep my specializations private rather than public so I'm accepting Krill's answer.
You can specialize just one function out of an entire template class on a specific type without specializing the entire class. It would look like this:
template <> void Foo<char>::doX() {
/* custom implementation here */
}
You rarely see this in practice, but this is totally legal C++ code.
Hope this helps!
std::string m_getY(char* p_msg)
{
return std::string(p_msg);
}
std::string m_getY(T* p_msg)
{
return p_msg->blah();
}
The problem here is that when T is char, you end up with two functions with identical signature.
You can make your method m_getY a member function template. And them make specialization of this function template for char* or simply define a method with a char* argument. In this case you will not have to duplicate the whole class.
std::string m_getY(char* p_msg)
{
return std::string(p_msg);
}
template<typename U>
std::string m_getY(U* p_msg)
{
return p_msg->blah();
}
will not conflict with each other (and the former is not a specialisation of the latter, as it is not a template)
Related
I want to provide a to_string(obj) function for every object type I create.
I found this question, applied the accepted answer, and it works. So far so good.
Then I created a new type, but forgot to write a to_string() for it (or better: I accidentally made it unreachable by ADL). The problem is: my program still compiles fine, and at runtime I get an obscure stack overflow(TM).
Is there a way to obtain a reasonable error message, instead?
Here is a small program to demonstrate the problem: an infinite recursion between notstd::to_string() and notstd::adl_helper::as_string().
#include <iostream>
#include <string>
namespace notstd {
namespace adl_helper {
using std::to_string;
template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t) );
}
}
template<class T>
std::string to_string( T&& t ) {
std::cout << "called" << std::endl; // <-- this is to show what's going on
return adl_helper::as_string(std::forward<T>(t));
}
class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("a"); }
//friend std::string to_string(const A &a) { return std::string("a"); }
};
}
int main(int argc, char** argv) {
notstd::A a;
std::cout << to_string(a) << std::endl;
}
I tried creating a wrapper function that accepts one more parameter, to be used to perform the an anti-recursion check, like this:
#include <iostream>
#include <string>
#include <cassert>
namespace notstd {
namespace wrap_std {
std::string to_string(double v, bool) { return std::to_string(v); }
/* .... etc..... */
}
namespace adl_helper {
using wrap_std::to_string;
template<class T>
std::string as_string( T&& t ) {
return to_string( std::forward<T>(t), true );
}
}
template<class T>
std::string to_string( T&& t, bool recurring = false ) {
std::cout << "called" << std::endl;
assert(!recurring);
return adl_helper::as_string(std::forward<T>(t));
}
class A {
/* both versions are needed, or the perfect forwarding candidate will
* always be chosen by the compiler in case of a non-perfect match */
//friend std::string to_string(A &a) { return std::string("A"); }
//friend std::string to_string(const A &a) { return std::string("A"); }
};
}
int main(int argc, char** argv) {
notstd::A a;
std::cout << to_string(a) << std::endl;
}
The problems here are:
I'd have to wrap all std::to_string() overloads
I'll only get a runtime error, but I feel the problem could and should be detected ad compile time
I'm probably adding some overhead, for something useful only during development: maybe I could add some macros to deactivate all this in release mode, but it would add even more work
Maybe I could use a template to wrap std::to_string() and create specializations for my types... this would be a quite different beast, but at least it would provide a compile time error if a suitable specialization is not available. I would have, again, to wrap all std::to_string() overloads, and I'd probably have to (almost) forget about ADL, at least until c++20 is supported by all compilers, If I understand well.
Does anyone have a better solution?
Thanks!
The idea of that accepted answer is different: you put A outside notstd namespace and then use qualified notstd::to_string instead of unqualified to_string. That is:
namespace notstd {
// ...
}
class A {
friend std::string to_string(const A&);
};
A a;
std::cout << notstd::to_string(a);
Now your code won't compile if there is no friend function. Moreover, you need only one friend function (taking const A&), because notstd::to_string(T&&) won't be present in the overload set inside adl_helper::as_string(T&&).
Putting A inside notstd screws everything up. You have infinite recursion problem and you need two friends to handle both A and const A cases in the presence of notstd::to_string(T&&) candidate: if only one friend is defined, that candidate is a better match in one of the cases because const qualifier should be added/dropped to invoke the friend function.
How can I save a pointer to a function without save its return type?
For example:
int GetInt() { return 5; }
string GetStr() { return "abc"; }
FunctionPointerClass GetAny;
int main()
{
GetAny = &GetInt;
auto var = GetAny();
GetAny = &GetStr;
auto var2 = GetAny();
cout << var << '\n' << var2;
}
Edit
A simple way to do this is use variant<> (thanks #sehe), like this:
#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<boost::variant<int, std::string>()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
But, it not too applicable for my project: a non-typed class. To use it, I will need stack all the used return types, to put it in template of variant<>. Like this:
class Var {
private:
void* _val;
template <typename T>
T& _Get() const {
return *((T*)_val);
}
// Static stack variable HERE
public:
val() {}
template <typename T>
val(T val) {
Set(val);
}
~val() {
if(_val != nullptr) delete _val;
}
std::function<boost::variant</*Stack*/>()> Get;
template <typename T>
void Set(T val) {
if(_val != nullptr) delete _val;
_val = new T(val);
Get = &_Get<T>;
// TODO Add 'T' to Stack
}
};
How can I do this?
Not exactly.
You can of course make it a function to print the value.
Or you can use std::variant/boost::variant to return either type.
Other techniques, like Type Erasure might also apply.
I flesh the last two of the approaches here:
Using variant<>
Live On Coliru
#include <boost/variant.hpp>
#include <string>
#include <iostream>
#include <functional>
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<boost::variant<int, std::string>()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
Prints
5
abc
Using type erasure
A related technique is type erasure, where you define a "concept" with supported operations (in this case, output streaming) and you hide it behind a polymorphic interface. E.g:
struct Printable {
template <typename T> Printable(T v) : _stored(new concrete<T>(v)) { }
friend std::ostream& operator<<(std::ostream& os, Printable const& p) {
return p._stored->print(os);
}
private:
struct interface {
virtual std::ostream& print(std::ostream& os) const = 0;
virtual ~interface() = default;
};
template <typename T>
struct concrete : interface {
concrete(T v) : v(v) {}
virtual std::ostream& print(std::ostream& os) const override {
return os << v;
}
T v;
};
std::unique_ptr<interface> _stored;
};
In that case you can make the whole program:
Live On Coliru
int GetInt() { return 5; }
std::string GetStr() { return "abc"; }
int main()
{
std::function<Printable()> Get;
Get = &GetInt;
std::cout << Get() << '\n';
Get = &GetStr;
std::cout << Get() << '\n';
}
I was going to write this as a comment, and it's not REALLY an answer, but it's a lengthy discussion on the subject of "return different types from the a function with the same name".
C++ doesn't take return type into concideration for overloading functions. In other words, std::string GetAny() and int GetAny() are considered as duplicates of the same function, because they only differ in return type. That's a restriction in the language definition, and you have to work around this restriction by "doing something other than return two different types".
As discussed in another answer, one solution is boost::variant, which is basically a way to define a class that can have multiple different types inside it, which has a type of "tag" to determine what it really contains, and various other clever stuff related to that. Makes it very neat in many ways.
However, it is only really useful for certain classes of problems. In many cases, your code still needs to understand what the data-type is, and having a function that may return a string, an integer or any other "random" data type isn't meaningful. Yes, it's handy to be able to define function pointers that return "any" type - but only in so far as you can have a table of the functions. Your code will not really work well if you do:
std::string s;
s += GetAny(); // Happens to be returning `int` in this call.
Just as bad:
int x = GetAny(); // Returning a string...
So, whilst you can write code that may return "any type", it's hard to make use of such a function without knowing what it returns. I've been programming professionally for over 30 years, and I have used function pointers for many things. So far, I've managed to not need to use this more than a handful times, and every time, it's been some form of solution similar to boost::variant (essentially returning a data-structure, where one field is describing the data-type itself). The two cases I can think of where I have used this are in my Lisp interpreter and my Basic intrepreter. They need a "variable type" that have the ability to hold various types of objects (integer, float, string, list [only in Lisp]). In my Pascal compiler, I do have a proper type system, so it doesn't need to have multiple types returned from a single function (or function pointer). I'd say "it smells funny" when this type of situation happens, and you should probably think about what it is you're trying to solve, and if this is really the right solution.
I'm writing C++ class that interfaces with a library. The library has a bunch of functions that look like the following:
Library.h
int FunctionA(int deviceNumber, ...);
int FunctionB(int deviceNumber, ...);
int FunctionC(int deviceNumber, ...);
int FunctionD(int deviceNumber, ...);
int FunctionE(int deviceNumber, ...);
Each instance of my C++ class has an associated deviceNumber which never changes, so I have deviceNumber stored as a member variable, and every time I call a library function, I pass the member in as the function call's first argument.
This is fine, and there's no real reason for me to change the way it is. But out of curiosity, I was wondering if C++ had any mechanism to "transform" arguments that would let me avoid passing the same argument in every call. The obvious way to accomplish this is to overload everything. Let's say my class is called Foo:
Foo.cpp
int Foo::FunctionA(...) {
// deviceNumber_ is a const member
return ::FunctionA(deviceNumber_, ...);
}
The only problem is that this requires a method for each function call, so as the library grows, it gets more and more annoying without a code generator.
Is there any general way to provide the overloading behaviour without actually overloading the functions? Is there a mechanism in C++ to "expand" an argument into multiple arguments? I'm imagining it would look like:
// These two calls are equivalent
FunctionA(deviceNumber, ...);
FunctionA(Magic(...));
// Magic() expands the arguments, adding deviceNumber
Even if the solution is much uglier and less readable than leaving everything alone, I'm curious if it's possible. After searching around, variadic templates seem to be the closest match, but I can't really wrap my head around how they could be used to accomplish this.
You might be happy with a generic relay function:
Live On Coliru
#include <iostream>
int foo1(int device_number, const char*) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*42; }
double foo2(int device_number) { std::cout << __PRETTY_FUNCTION__ << "\n"; return device_number*3.14159; }
struct facade {
facade(int dn) : device_number(dn) {}
template <typename F, typename... A>
auto call(F&& f, A&&... args) const {
return std::forward<F>(f)(device_number, std::forward<A>(args)...);
}
private:
int device_number;
};
int main() {
facade dev(2);
std::cout << dev.call(foo1, "yes ma'am") << "\n";
std::cout << dev.call(foo2) << "\n";
}
I would probably choose a marco in the cpp file as the easiest solution (strictly in the cpp file though)
Variadic templates could help here too. However it sounds like you are doing something embedded and that might be an issue.
Also, I'm not sure if you mean that each FunctionA is overloaded or FunctionA refers to exactly one function.
Anyway, my template solution will help if there are multiple FunctionAs
template<typename... Args>
int Foo::FunctionA(Args&& ...args) {
return ::FunctionA(deviceNumber_, std::forward<Args>(args)...);
}
I put pseudo code , for C++ type structure.
Class Prototype might be following forms.
class Foo {
private private_member_of_deviceNumber;
....
int FunctionA(...);
....
}
Foo Class constructor will assign deviceNumber to private member variable.
class Foo::Foo(int deviceNumber) {
int private_member_of_deviceNumber = deviceNumber;
}
Foo Class member FunctionA(...) will like this form.
int Foo::FunctionA(...) {
return ::FunctionA( private_member_of_deviceNumber , ...);
}
How about like this way?
Say I have a templated class:
template <typename T>
class foo {
void do_someting(T obj) {
// do something generic...
}
};
and I want to specialize do_something, but within it I want to call the "normal" do_something function:
template<>
void foo<MyObj>::do_something(MyObj obj) {
// do something specific...
// and ALSO do something generic!
}
is there a way to refer to the normal version of do_something within my specialized function? Or do I just have to copy the code?
(I know that I could refactor foo in such a way that I wouldn't have this exact problem, but as it happens I can't really modify the "real" foo, as it's heavily-shared code.)
No. Your specialization is the only definition that will exist for the MyObj type argument. But, consider modifying the foo template in this manner, which will be transparent to the current users of the template:
template<typename T>
class foo {
void prelude(T &obj){ // choose a better name
/* do nothing */
}
void do_something(T obj){
prelude(obj);
// do something generic...
}
};
Then define a specialization for the prelude:
template<>
void foo<MyObj>::prelude(MyObj &obj){
// do something specific
}
This is somewhat similar in structure to the main use case for private virtual members. (Sort of. Not really. But it's what inspired me in this answer.)
You might also consider a type that is not MyObj, but implicitly converts to it, but the best way would be to refactor and perhaps extract the common generic something.
#include <iostream>
#include <boost/ref.hpp>
typedef int MyObj;
template <typename T>
struct foo {
void do_something(T obj) {
// do something generic...
std::cout << "generic " << obj << '\n';
}
};
template<>
void foo<MyObj>::do_something(MyObj obj) {
// do something specific...
std::cout << "special " << obj << '\n';
// and ALSO do something generic!
foo<boost::reference_wrapper<MyObj> >().do_something(boost::ref(obj));
}
int main()
{
foo<int> f;
f.do_something(10);
}
Yes, this this is actually quite straightforward. You just let the main, generic version of your function serve as a pass-through to an 'implementation' generic function which doesn't get partially specialized, then you can just call that from the specialized version of the initial function as needed.
template <typename T>
class foo
{
void do_something(T obj)
{
do_something_impl(obj);
}
void do_something_impl(T obj)
{
// do something generic...
}
};
Now the specialization can call the generic version without a problem:
template<>
void foo<MyObj>::do_something(MyObj obj)
{
// do something specific...
do_something_impl(obj); //The generic part
}
I think this closer to your original intentions than Steve M.'s answer, and is what I do when faced with this issue.
consider this simple and pointless code.
#include <iostream>
struct A {
template<int N>
void test() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a.test<1>();
}
It is a very simple example of a function template. What if however, I wanted to replace A::test with an overloaded operator() to make it a functor?
#include <iostream>
struct A {
template<int N>
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A a;
a<1>(); // <-- error, how do I do this?
}
Certainly if the operator() took parameters which were dependent on the template, the compiler could possibly deduce the template. But I just can't figure out the proper syntax to specify template parameters with a parameterless functor.
Is there a proper way to do this?
Obviously, this code would work since it bypasses the functor syntax:
a.operator()<1>();
but that kinda defeats the purpose of it being a functor :-P.
You can only call
a.operator()<1>();
but that would not be using a functor. Functors need a non template operator(), as they must be able to be called as varname() and that won't work with your code.
To make it a real functor change your code a template class (functors are classes):
#include <iostream>
template<int N>
struct A {
void operator()() {
std::cout << N << std::endl;
}
};
int main() {
A<1> a;
a();
}
There's not another "direct" way I know other than the:
a.operator()<1>();
syntax. If you're open to changing the code, moving the template parameter to the class would work, or using a (boost|tr1)::bind to make a (boost|tr1)::function object.
You are trying to pass a template parameter to an instance of an object, which as far as I know is not allowed. You can only pass templates parameters to template functions or template objects.
a.test<1>(); and a.operator()<1>(); work because they are serving as template functions.
Use boost::bind (check out boost libraries) to fix it though.
struct A {
void operator()(int n) {
std::cout << n << std::endl;
}
};
int main(int argc, char* argv[]) {
A a;
boost::function<void()> f = boost::bind<void>(a, 1);
f(); // prints 1
return 0;
}
And you don't even have to mess with templates!
You're stuck. Have you considered something like
struct A {
template<int N>
struct B
{
void operator()()
{ std::cout << N << std::endl; }
};
template<int N>
B<N> functor() {return B<N>();}
};
int main()
{
A a;
a.functor<1>()();
}
Nope, there's no way around it. Like you said, you have to either call the operator explicitly (which defeats the purpose), or the template arguments must be able to be deduced by the compiler.