(Don't bust my nuts about using std::auto_ptr<>, this isn't my code, it's auto-generated. I'm just trying to interface to it.)
I have a function with the following signature:
std::auto_ptr<T> gFunction(const std::string&, int, const int&)
This function is overloaded like 588 times so assigning it to a boost::function is ambiguous. Ok, fine, I'll just recast it and then assign it.
It's cumbersome to type like this:
std::auto_ptr<T> (*func)(const std::string&, int, const int&) = &gFunction
I want to typedef this so I can use it in the following way:
function_type func = &gFunction
So I tried to typedef
typedef std::auto_ptr<T>(*funct)(const std::string&, int, const int&) function_type;
But my typedef is returning a error: expected ‘;’ before ‘function_type’
Any ideas? I'm probably missing something simple.
Just do it this way:
typedef std::auto_ptr<T>(*function_type)(const std::string&, int, const int&);
Also keep in mind, that std::auto_ptr is deprecated since C++11. If you can, you should use std::unique_ptr instead.
In C++11 you can also use the std::add_pointer type trait to add a pointer to a function type (if that makes it more intuitive to you):
#include <type_traits>
typedef typename std::add_pointer<
std::shared_ptr<T>(const std::string&, int, const int&)
>::type function_type;
Also, as mentioned by Mike Seymour in the comments, you may consider defining the type alias function_type as a function type (as the name would suggest), rather than making it a function pointer type (just drop the * to do that).
The proper syntax for declaring a typedef should mimic a variable declaration. Syntactically, they are the same except you prefix it with 'typedef'. Semantically the declared names form very different purposes(one makes a variable, one makes a type)
just as you typed the following to declared a variable
std::auto_ptr<T> (*func)(const std::string&, int, const int&);
you can make this a typedef just be adding a "typedef" to the front
typedef std::auto_ptr<T> (*func)(const std::string&, int, const int&);
Related
I want something like this:
std::tuple<int, bool, double> MyFunction_1 (void);
void MyFunction_2 (decltype (MyFunction_1) ¶ms);
Obviously, in this example a code pointer to function would be passed.
I want to have the equivalent of this:
void MyFunction_2 (std::tuple<int, bool, double> ¶ms);
Is it possible to do so?
decltype (MyFunction_1) will give you the type of MyFunction_1 (i.e. the function type std::tuple<int, bool, double> ()), you need to emulate a function calling 1 (via adding ()) to get the return type (i.e. std::tuple<int, bool, double>), e.g.
void MyFunction_2 (decltype (MyFunction_1()) ¶ms);
// ^^
1 The expression is evaluated at compile-time, the function won't be called at run-time actually.
The type of MyFunction_1 is not std::tuple<int, bool, double> - informally you can think of it as a function pointer. In fact &MyFunction_1 decays to itself and is certainly a pointer.
So decltype(MyFunction_1) is not what you want.
The solution is to write decltype(MyFunction_1()). The type of MyFunction_1() is std::tuple<int, bool, double>. Note that this doesn't actually call the function; it's rather like sizeof in that respect.
using RetType = std::invoke_result<decltype(f)>::type;
Play with it : https://gcc.godbolt.org/z/AE7lj_
#include <iostream>
#include <deque>
using namespace std;
main()
{
typedef void (deque<int>::*func_ptr)(int);
func_ptr fptr = &deque<int>::push_back;
}
Im trying to get pointer to this function but I get a compilation error
error: cannot convert ‘void (std::deque<int>::*)(const value_type&) {aka void (std::deque<int>::*)(const int&)}’ to ‘func_ptr {aka void (std::deque<int>::*)(int)}’ in initialization
func_ptr fptr = &deque<int>::push_back;
I want to do this so that I can get pointer to different member functions on the basis of different conditions.
I referred this link.
As said in the accepted answer, the problem is that the type signature is different -- for a std::deque<T>, push_back only has an overload that accepts T const&, and not T directly. typedef void (deque<int>::*func_ptr)(const int &) is a perfectly concise and cromulent way to write this.
I wanted to address a C++11 way to do this -- type aliases. One may first wonder "why not use auto?" This is not possible because the function being accessed is an overloaded function, and auto does not know which of the overloads to access. Because the original question embeds the knowledge of the function type being void(int), the statement &deque<int>::push_back selects the correct overload. The problem with the simpler statement is that it bakes in knowledge of the container and the type being contained. If you want to change to a std::vector, or from int to short, you'll have to make all new types. With type aliases, we can templatize everything to avoid embedding type knowledge:
using func_ptr = void(Cont::*)(typename Cont::const_reference);
We can do something simple, as before:
func_ptr<deque<int>> fptr = &deque<int>::push_back;
...or we can refer to a container somewhere:
vector<short> container;
...looking up its type at compile time, and storing a pointer to its push_back function, all without caring what the container is:
using container_type = decltype(container);
func_ptr<container_type> fptr2 = &container_type::push_back;
push_back() takes a const T & parameter, as the error message states:
cannot convert ‘void (std::deque::*)(const value_type&) ...
Change your type alias to:
typedef void (deque<int>::*func_ptr)(const int &);
There is a bigger problem with what you are trying to do. Implementations are allowed to add default parameters to any member functions, so the actual signature for push_back() might be different. It can even add additional functions with the same name (but a different signature).
I advise against taking pointers to container members function. You are usually better of without it.
I understand the basic problem in passing the address of a member function outside of its class. I get the feeling that mem_fn() might be the solution but I am having trouble with the specifics.
I have a member function in class p that is currently declared as
typedef void (*valNamedFlagsCallback)(const int, const bool);
bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], valNamedFlagsCallback callBack);
In class e I am trying to call valNamedFlags with
pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::mem_fn(&e::setStatement));
(I started out without the mem_fn() but of course that has the classic "pointers to member functions" problem. I've tried both &e::setStatement and just plain &setStatement.)
FWIW, setStatement is prototyped as
void setStatement(const int ifcid, const bool isAffirmative);
Everything works if I eliminate the mem_fn() and declare setStatement as static. I'm just pointing that out as a way of saying that I have eliminated all of the other possible issues; my only issue is the "pointers to member functions" problem. Unfortunately, setStatement() needs to be a member function, not a static.
The specific error I am getting in MS VS 2010 is
bool p::valNamedFlags(const OptBlk *,const char *,const int [],const char *[],p::valNamedFlagsCallback)' : cannot convert parameter 5 from 'std::tr1::_Mem_fn3<_Rx,_Pmf,_Arg0,_Arg1,_Arg2>' to 'p::valNamedFlagsCallback'
I would like to keep the callback declaration independent of class e; that is, I do not want to go to
typedef void (*e::valNamedFlagsCallback)(const int, const bool);
because I want to keep p more generalized than that.
Is mem_fn() the right solution or am I way off base? If so, how should I be declaring the callback in the valNamedFlags() prototype?
Or should I be pursuing a different approach?
Actually, you'll have a problem doing bind-like stuff as some suggested, since your callback is defined as a simple function pointer, and not a callable.
If you can afford to do it, you can change your
typedef void (*valNamedFlagsCallback)(const int, const bool);
to something like
typedef std::function<void(int, bool)> valNamedFlagsCallback
(also noting that const on value parameters doesn't affect the signature of the function), then you can use std::bind(),
using namespace std::placeholders;
pInstance->valNamedFlags(operand,
"Statement types",
statementsSubscripts,
statementsNames,
std::bind(&E::setStatement, e, _1, _2));
or you can use lambdas:
pInstance->valNamedFlags(operand,
"Statement types",
statementsSubscripts,
statementsNames,
[&](int i, bool b) { e->setStatement(i, b); });
If you must keep it as a simple function, then you'll have to send one which references the right object as a global/static variable.
You need to bind an instance on it to call via a member function pointer. (i.e. std::bind(&e::setStatement, eInstance, _1, _2), suppose eInstance is a pointer to an object of class e).
using namespace std::placeholders; // for _1, _2, _3...
pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::bind(&e::setStatement, eInstance, _1, _2));
Note that the return value of std::bind (which is unspecified) doesn't match the free function pointer type valNamedFlagsCallback, one of the solutions is to use std::function.
typedef std::function<void(const int, const bool)> valNamedFlagsCallback;
Simplified demo
Got it!!! THANKS ALL!!!
Prototype:
bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], std::function<void(int,bool)> callBack);
Call:
valNamedFlags(..., std::bind(&e::setStatement, this, _1, _2));
Actually runs and calls setStatement with the proper arguments.
I have the following piece of code:
#include <functional>
template <typename T>
class TD; // For displaying type
void f(int, int, int) { }
int main() {
auto g = std::bind(f, std::placeholders::_1, 2, 2);
TD<decltype(g)> td1;
return 0;
}
In this code TD is a template trick for showing its template argument passed via decltype.
Output of the compiler follows (compiled in C++14 mode):
prog.cpp: In function 'int main()':
prog.cpp:10:18: error: aggregate 'TD<std::_Bind<void (*(std::_Placeholder<1>, int, int))(int, int, int)> > td1' has incomplete type and cannot be defined
TD<decltype(g)> td1;
^
Well, incomplete type error is of course excepted. But what makes me curious in this error message is std::_Bind<void (*(std::_Placeholder<1>, int, int))(int, int, int)>. I can comprehend that std::_Bind is a proxy class which defines operator() and makes our purpose possible. But its template argument void (*(std::_Placeholder<1>, int, int))(int, int, int) made me woow! How should I interpret it? Does it have any usefulness in user-land code? How can I create my own classes making use of this declaration?
void (*(std::_Placeholder<1>, int, int))(int, int, int)
This declares an unnamed function taking three parameters (std::_Placeholder<1>, int and int) and returning a pointer to a function that takes three ints and returns void.
Let's simplify a little. First consider a simple function declaration:
void f(int)
Now, in parameter declarations (of functions or templates) you can omit the name and you get
void (int)
which, if used in a parameter list of a function declaration, would be equivalent to a function pointer void(*)(int).
A function that returns a function pointer is declared like this:
void (*f(int))(int);
// ^ ^ <- this pair of parentheses changes
// the order in which the declaration is parsed.
// Without it, the return type would be `void*`
// and you'd get a syntax error
Now you can remove the name f and you basically get the same thing that you were asking about.
Its uses? Apparently it's useful when implementing std::bind :) I can't think of anything else right now...
C++11 marked the advent of function which made defining function pointers far easier:
Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
So for example let's say that you needed to take in a function pointer to string foo(int param) { return to_string(param); } in one of your functions. Pre-C++11, your function would need to look like:
void bar(string (*func)(int)) { cout << func(13) << endl; }
Let's go a step further and say you wanted to expand foo to: string foo2(int lhs, int rhs) { return to_string(lhs + rhs); }. But now you want to cram that back into bar. Doing this bar(bind(&foo2, placeholders::_1, 42)); would give you an error like this:
cannot convert 'std::_Bind_helper (*)(int, int), const std::_Placeholder<1>&, int>::type {aka std::_Bind (*(std::_Placeholder<1>, int))(int, int)>}' to 'std::string (*)(int) {aka std::basic_string (*)(int)}' for argument '1' to 'void bar(std::string (*)(int))'
You could get around this error by creating a function that took an implementation specific argument, like: void bar2(_Bind<string (*(_Placeholder<1>, int))(int, int)> func) { cout << func(13) << endl; } which could successfully be called with: bar2(bind(&foo2, placeholders::_1, 42));. The reason that this is implementation specific is that the types: _Bind and _Placeholder are non-standard. In fact the return of bind is:
A function object of unspecified type T
Which brings us to function. If you weren't already turned off by the syntax the limitations of a function pointer, you'll need to take a function parameter to accept an object created by bind. Let's make a new bar using function:
void bar3(function<string(int)> func) { cout << func(13) << endl; }
This is capable of accepting both the traditional function pointer and the bind functor. Additionally it can handle lambdas, so you can do this: bar3([](int param) { return to_string(param); });
I've created a live example so you can play around with this some hopefully the benefits of the function object are clear.
Does somebody know, why this compiles??
template< typename TBufferTypeFront, typename TBufferTypeBack = TBufferTypeFront>
class FrontBackBuffer{
public:
FrontBackBuffer(
const TBufferTypeFront front,
const TBufferTypeBack back): ////const reference assigned to reference???
m_Front(front),
m_Back(back)
{
};
~FrontBackBuffer()
{};
TBufferTypeFront m_Front; ///< The front buffer
TBufferTypeBack m_Back; ///< The back buffer
};
int main(){
int b;
int a;
FrontBackBuffer<int&,int&> buffer(a,b); //
buffer.m_Back = 33;
buffer.m_Front = 55;
}
I compile with GCC 4.4. Why does it even let me compile this? Shouldn't there be an error that I cannot assign a const reference to a non-const reference?
The thing is that if type T is int&, then the type const T is not const int&, but int & const. The illegal top-level const on a reference is ignored in template substitutions and typedef results.
If, on the other hand T is const int, then T& is const int&
When TypeBufferFront is int&, const TBufferTypeFront is equivalent to int& const, where the const is ignored during template substitution, since all references are constant, even if what they refer to is not.
So, when instantiated with int&, your constructor is effectively FrontBackBuffer(int&, int&), which works as given.
This is an example of why many people will use T const instead of const T, to make it clearer how the substitution occurs, as well as allow them to read the cv-qualifiers from right to left.
For the code to do what you want it to do, it would have to read:
FrontBackBuffer(
typename std::remove_reference<TBufferTypeFront>::type const& m_front,
typename std::remove_reference<TBufferTypeBack>::type const& m_back): ////const reference assigned to reference???
m_Front(m_front),
m_Back(m_back)
{
};
which has the added "feature" that it turns other types into const references when used to construct FrontBackBuffer.
Now this isn't perfect. This prevents temporary arguments to FrontBackBuffer from being moved, and passes even small cheap to copy types (like char) by reference instead of by value. There are standard C++0x techniques to do this that are a bit awkward to write if you care.
FrontBackBuffer::m_Front is of type TBufferTypeFront which translates to int& in your template instantiation. There is nothing wrong with assigning to an int&.