My problem is std::tuple has no member function like
auto t = std::make_tuple(1,2,"foo");
t.get(1);
how can I implement such a function when I create a wrapper class arround std::tuple
Such a function cannot exist (in current C++ standards) because function arguments are a run-time mechanism, but return types need to be known at compile time. So the latter cannot depend on the former.
Use std::get instead:
auto v = std::get<1>(someTuple);
To get a value from a tuple you should use std::get<0>(tuple)
You can't have a get function like you want, because tuple elements are not necessarily of the same type (in your example you have ints and a string). What would the return type of this get function be?
You can add a template get function, so that derived_tuple.get<0>() will return the first element.
There are actually two questions here. The first is
why get has a template integral argument rather than a accepting this
value as a function argument.
This has been answered.
The other question is
why get is a free function rather than a member function
To this the answer seem to be - so that called on templated types, it would not require usage of keyword typename. Example. Suppose, tuple would have a get as a member, it would have to be called like that in below code:
template <class T> void foo(T tuple) {
tuple.template get<1>() = 42;
}
This template is certainly a nuisance.
Related
I was wondering if writing anything resembling this declaration (making use of the parameter pack) is possible.
decltype(auto) (*funcPtr)(...);
If possible, I would also like to know about alternative ways to declare such a pointer.
C++ is a statically typed language. All function argument types and return types must be known at compile time. You cannot declare a function that returns arbitrary types (well, I guess you could return std::any, but I can't think of a case where you'd want to).
You can use templates, however, to create function templates where the compiler will stamp out multiple versions of a function for you, so you don't have to write them all yourself.
Remember that auto and decltype(auto) is not magic. They are just syntactic sugar for what you'd otherwise write yourself if they didn't exist. They do not enable any new features that weren't already in the language. They just make such features easier to use.
No, there is no type such as pointer to function "that returns anything". There are only pointers to a function that returns some type or void. auto merely deduces the type from an initialiser, and there is nothing to deduce the type from in your example.
You can however have a function template where the instance of the template is a function that returns a type specified by a template argument:
// function template
template<class T>
T foo() {
return {};
}
Likewise, you can have a variable template that is a pointer to function whose return type is specified by a template variable:
// variable template
template<class T>
T (*funcPtr)() = foo;
// example usage
int main() {
return funcPtr<int>();
}
So I have something for example
auto a = getMyTuple();
which will eventually be real type of std::tuple<(some args)>
Now I want to store this in a class which has a template since I dont know the type yet. Something along the lines of
template<typename T>
class my_tuple
{
public:
T mt;
my_tuple(T t)
{
mt = t;
}
};
My question is, is there a way to get the type returned by auto, so I can pass it into the template class like
my_tuple<getType(a)> myTup(a);
That's what decltype is for:
my_tuple<decltype(a)> myTup(a);
You want decltype (since C++11):
my_tuple<decltype(a)> myTup(a);
You could implement a factory function that will construct your objects, the same way as std::make_tuple() constructs std::tuple.
(simplified version, see more plausible version in the link above or in your favorite standard library's source code)
template <typename T>
my_tuple<T> my_make_tuple(T t) {
return my_tuple<T>(t);
}
auto myTup = my_make_tuple(a);
Function call template argument deduction will figure out the types automagically, so you don't need to worry about explicit types anymore.
This is how they do it in standard library.
See this talk by Stephan T. Lavavej: Don’t Help the Compiler (towards the second half of it)
Update:
I think that the solutions with decltype posted around are ugly and error prone, because of the repetition of the variable name (violation of DRY principle). Also, decltype is unnecessary here as types can be deduced automatically with the use of a function wrapper. Finally, if your tuple would have 25 parameters will you write decltype 25 times? What if you accidentally mix the order of types and the order of parameters?
I'm new to C++ and I'm learning about lambdas,functors and callables, and I know that there's a wrapper class, namely std::function that allows callables of different types to be stored and called (as long as the have the same call signature,or function type).
Now, I understand that you can have function with function type parameters that are really just function pointer parameters as in :
void fun(int,int*(int,int&));
which is nothing more than a function that takes an int and a function pointer to a function like int *f(int,int&),even if the language allows me to pass a function as an argument (with or without the ampersand).Infact, the function parameter list might as well be written as:
void fun(int,int*(*)(int,int&));
Now,back to the std::function type
I know that I can instantiate std::function with a function type and that allows any kind of callable to be passed to the wrapper. But, a function type is not a type I can use as a template type argument in any instantiation such as:
std::vector<int(int)> f_vec;
instead, I should make a vector of function pointers
std::vector<int(*)(int)> f_vec;
and that would allow me to insert pointers to function,but not functors or lambdas.
So, my question is, how can I instantiate a template with a type argument like a function type?? what's happening under the hood in the library std::function type.I mean a function type seems to me a type I cannot use in templates?? pleas can you make things a little clearer,as I'm just beginning to learn these topics. Thanks
The reason why you cannot write std::vector<int(int)> is not something fundamental about using function types as template parameters. That's perfectly valid. It's just what std::vector<T> does with the T (like operate on it by value) which makes std::vector<int(int)> illegal.
This can be shown by using std::vector<int(int)> in a context where nothing bad happens, such as this:
typedef std::vector<int(int)> StillOk;
StillOk *p = nullptr;
As long as the template doesn't actually try to do anything illegal with int(int), it's fine.
So, as long as your template deals with its template parameter in a way which is legal for function types, you can use it with function types. Here's a hypothetical example:
template <class T>
struct MyPointer
{
T *p;
T& operator* () const { return *p; }
};
It's now perfectly legal to instantiate MyPointer<int(int)> and use its operator *, because it will only ever involve expressions of type int (*)(int) and int (&)(int). [Live example]
And that's pretty much also what std::function<T> does with its T—only things which are legal with a function type.
How can I in C++ make a function accept every Object, so I can give it numbers, String or other Objects. I am not very well in C++, I hope it's not a totally stupid question...
Edit: Ok, an example: if you want to try to wrap the std::cout streams into normal functions, that funtion should be able to accept everything - from Integers over Floats to complex Objects. I hope it's more clear now!
You can overload your function for different types, i.e.
size_t func(int);
size_t func(std::string);
Alternatively and/or additionally, you can provide a function template, which is a way to tell the compiler how to generate your function for any particular type, for example
template<typename T>
size_t func(T const&) { return sizeof(T); }
You may use more advanced techniques such as SFINAE to effectively overload those template functions, i.e. to use different templates for different kind of types T (i.e. integral types, pointer, built-in types, pod, etc). The compiler will then pick the best-fitting func() (if any) for any function call it encounters and, if this is a template, generate an appropriate function.
This requires no re-coding.
A completely different approach is to use a generic erasure type, such as boost::any, when the function will need to resolve the expected types at coding-time (as opposed to compile-time):
size_t func(boost::any const&x)
{
auto i = boost::any_cast<const int*>(x);
if(i) return func(*i);
// etc for other types, but this must be done at coding time!
}
You can use templates for this purpose:
template <typename T>
void foo(T const & value)
{
// value is of some type T, which can be any type at all.
}
What you can actually do with the value may be rather limited without knowing its type -- it depends on the goal of your function. (If someone attempts to call the function with an argument type that causes that function specialization to be ill-formed then your template function will fail to instantiate and it will be a compile-time error.)
I'm not sure what you're trying to accomplish, but you can pass a void pointer as a parameter.
void foo(void* bar);
If I understood you correctly you might wanna try using templates http://en.cppreference.com/w/cpp/language/function_template
You are probably looking for templates.
I suggest you read this.
Am I able to implement the following function in C++?
I would like to keep the myInstance variable unspecified until the callback method is called, instead of containing it in a boost::bind instance.
MyClass *myInstance;
void call(/* boost::mem_fn */ callback)
{
// Somewhere in this function, the operator()() method
// is called on the callback instance
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
I understand that boost::mem_fn is a function which returns a particular object, but I'm unsure of its type. The documentation says unspecified as its return type. One of the boost::bind constructors takes this type as a parameter, but I'm unable to find the actual declaration in its implementation. Also, am I even allowed to store my own instance of this particular type, or is this strictly for use by boost functions?
This is one of those cases where it seems that the compiler is doing some very magic stuff.
The reason there isn't really a well defined type is that the type returned from bosst::mem_fn is always assumed to be a template parameter of the function it's passed to. Let me show you an example:
std::for_each has a signature like this:
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
This little slice of magic has two template parameters, an InputIterator and a Function. These could have been called anything, but the names given to them describe how they will be used, really, are more self-documenting names than a real type. The type of InputIterator may well be something like std::vector<foo>::iterator - the point is that the compiler will automatically resolve what an "InputIterator" is at compile time. It can figure this type out for you.
The same is true of Function. As long as you pass it something that can be called - that is, has a version of operator() that is compatible with what gets called in for_each, then you never need to know what Function is.
So the short answer is, make your call function take a template parameter:
template<typename SomeSortOfFunction>
void call(SomeSortOfFunction callback)
and then the compiler should resolve SomeSortOfFunction to be whatever the type is that is returned from boost::mem_fn
The return type of boost::mem_fn is unspecified. You should use either Matt's approach (i.e. pass it as a template), or if separate compilation is important to you, use type erasure:
MyClass *myInstance;
void call(boost::function<void(MyClass*)> callback)
{
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
The return type of mem_fn is not something you should ever explicitly type or store. It is generated at compile time via the types of the arguments.
It can, however, be stored via std::function (or boost::function).
The operator() signature of men_fn is the original method arguments with a possibly const pointer to the class prepended, and the same return value type. Just create a std::function with that signature, and it can take the men_fn type and store it.
In short if you have a zero argument method for class foo that returns void try storing the men_fun in a std::function<void(foo *)>.