I have function:
FARPROC PUDSClass::getFunction(LPSTR szName)
{
if(handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
}
I am trying to rewrite it as lambda function.
FARPROC lambda_decToStrHex = [&](LPSTR szName)
{
if (handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
};
But I get error of inconsistent types "int" and "int (attribute(stdcall)*)()".
If I write it like this, it works ok:
auto getFunction = [&](LPSTR szName)
{
return GetProcAddress(handleDLL, szName);
};
From what I understood, lambda cannot handle return NULL or GetProcAddress(), but why can a normal function do so?
FARPROC lambda_decToStrHex = ...;
This will create a variable lambda_decToStrHex, it's type is FARPROC, which, according to documentation, is defined as
int (FAR WINAPI * FARPROC) ()
It is a function returning int and accepting no parameters. This simply doesn't match the type of your lambda.
If at all, you need a function pointer of correct type the lambda can decay to, a function accepting a C string and returning a FARPROC pointer (in short: pointer to function returning function pointer):
FARPROC (*lambda_decToStrHex)(LPSTR) = ...;
Solely: Your lambda cannot decay to a function pointer, as it has a non-empty closure:
... = [&](LPSTR name) { /* ... */ };
// ^ ^ uses dllHandle, which thus gets part of closure
So all that remains is assigning the lambda to a variable thetype of your lambda, which you get by auto.
Edit: return NULL;:
'Lambda' is a red herring here, it is not an issue of lambdas, but of any function having deduced return type (auto f() { ... }). NULL typically is defined as (void*)0, (but can look differently as well), so you get two different return types (void* and FARPROC) at the two exit points of the (in this case) lambda. Which return type should now be deduced?
At very first, you shouldn't be using NULL at all any more, it is a macro coming from C, whereas C++ provides a keyword for: nullptr. Solely, it won't solve the issue, as it has it's own type (std::nullptr_t) which still differs from FARPROC. A cast then can solve the issue (that actually would work with the macro as well):
return static_cast<FARPROC>(nullptr);
Now both exit points have the same return type and we are fine. A trailing return type achieves the same:
[&](LPSTR) -> FARPROC { ... }
nullptr automatically decays to correct pointer type (so you don't need a cast); NULL macro, without a cast and depending on how being defined, can (but needn't) fail, though.
Another solution would be one single, well defined exit point:
[&](LPSTR)
{
FARPROC function = nullptr;
if(dllHandle)
function = get();
return function;
}
Why did it work with the normal function then? Well, you explicitly specified the return type (FARPROC f(...)), which is equivalent to having a trailing return type. Additionally, the fact that it compiled and the error message:
"int" and "int (attribute(stdcall)*)()"
^^^
reveal that your compiler obviously defines NULL without the void* cast:
#define NULL 0
or similar – and 0 literal decays to null pointer as well...
Since you specify the return type FARPROC in normal function, NULL (0, which is int type) will implicitly convert to FARPROC type (which is int (attribute(stdcall)*)()).
You can using using -> to specify the return type with lambda:
auto lambda_decToStrHex = [&](LPSTR szName) -> FARPROC
{
if (handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
};
Related
I want to return a boolean or success/failure enum from the function and modify an argument by reference. However, I want to construct a reference in the calling function instead of copying the value.
I have some container (say 'example_q' of type std::queue). queue.front() will return a reference to the value stored in the queue. I can make a copy of that reference (example A) or I can take a reference of that reference (example B), allowing the value to stay in the queue but be utilized outside of it.
A)
int a = example_q.front();
B)
int& b = example_q.front();
Using this difference I could also return the queued value:
A)
int get_front()
{
int a = example_q.front();
return a;
}
B)
int& get_front()
{
return example_q.front();
}
Using option 'B' I can avoid unnecessary copies without moving the data out of the queue via std::move() semantics.
My question is, can I do 'B' via an argument passed by reference? Would I need to use std::move()/rvalues/&& somehow?
void get_front(int& int_ref)
{
// somehow don't copy the value into referenced int_ref, but construct
// a reference in the caller based on an input argument?
int_ref = example_q.front();
}
The problem this would solve is making API match other functions that modify reference arguments but return a success/failure value, ie:
if(q.get_front(referrence_magic_here))
{
...
}
I could reverse the order to get the desired result, IE:
int& get_front(bool& success)
{
...
}
But I'd rather keep the pattern of my API as well as being able to do it via a single line in the if() statement if possible.
Perhaps something like:
bool get_front(int&& int_rvalue)
{
...
int_rvalue = example_q.front();
...
return true_or_false;
}
void calling_func()
{
...
if(get_front(int& magical_ref))
{
... //use magical_ref here?
}
...
}
No, you can't do that.
Other than in its initialiser, a reference behaves like the thing it refers to. By passing it as a function argument, you "hide" the initialiser from the part that wants to do the assignment. So, the function has no access to the referencey behaviour of the thing.
You will have to use pointers if you want to do that:
void get_front(int*& int_ptr)
{
int_ptr = &example_q.front();
}
int* ptr = nullptr;
get_front(ptr);
// optional:
int& ref = *ptr;
(Ew!)
Option B was fine.
This code is invalid C++:
if(get_front(int& magical_ref))
You cannot declare a new variable as you're passing it to a function. And because a reference variable must be declared and initialized at the same time, it wouldn't be possible to have a reference be initialized by passing it to a function.
You could however, do this:
if(int &magical_ref = get_front()) {
But note that you'd be checking whether magical_ref is 0 or not, which is different from the condition you have in your example.
If your logic is as simple as comparing the int, you could do:
if (int& magical_ref = get_front(); magical_ref == 42)
You can return a std::tuple<int&, /* status condition */> and check the status. For example:
std::tuple<int&, bool> get_front() {
static int example = 0;
return {example, false};
}
...
// C++17's structured bindings + if statement with initializer
if (auto [ref, success] = get_front(); success) {
ref = 42;
}
Demo
In my C code, I have the following lines:
void* (*functionSteps[numSteps])();
functionSteps[0] = (void*) filterEvenFoos;
functionSteps[1] = (void*) timesFooByTwo,
functionSteps[2] = (void*) mapFooToBar;
Which works fine. I have an array of functions that return a void* type and take any number of inputs.
I tried to do the same in C++ and I'm getting the error
assigning to 'void *(*)()' from incompatible type 'void *'
Is this not possible in CPP?
Is this not possible in CPP?
functionSteps[0] = (void*) filterEvenFoos;
No, it is not.
It is not really valid C either.
Regarding Function To Pointer Conversion
From https://en.cppreference.com/w/c/language/conversion#Function_to_pointer_conversion:
Any function designator expression, when used in any context other than
as the operand of the address-of operator
as the operand of sizeof
undergoes a conversion to the non-lvalue pointer to the function designated by the expression.
It does not say anything about converting a void* to a function pointer.
Regarding Conversions From void*
You can convert a void* to an object pointer.
From https://en.cppreference.com/w/c/language/conversion#Pointer_conversions:
A pointer to void can be implicitly converted to and from any pointer to object type with the following semantics:
If a pointer to object is converted to a pointer to void and back, its value compares equal to the original pointer.
No other guarantees are offered
Please note even in that section, there is no mention of converting a void* to a function pointer.
It's not clear to me why your computer does not report it as an error.
You can use
functionSteps[0] = filterEvenFoos;
if filterEvenFoos is of the right type of function. If the declaration of filterEvenFoos does not exactly match the expected type, i.e. a function that takes no arguments and returns a void*, then you can't use that either.
Is this not possible in CPP?
Strictly speaking, no, due to type safety and other rules governing function prototypes. However, depending on your needs, that C code can be ported to C++.
Firstly, it should be noted that the function signature of void* fn(); in C is not the same in C++. In C++ to get the same function signature, you need to introduce variadic arguments like so: void* fn(...);, however, it should be noted that you cannot access the variadic arguments portably for a function signature like this.
In C++, void* fn(); is the same as void* fn(void); in C. To this, if your functions had variable inputs in C, you would need to do a little extra work in C++ using the variadic argument list.
For example, if your code were something similar to the following C code:
#include <stdio.h>
#define NUM_STEPS 3
static void* filterEvenFoos(void)
{
printf("42\n");
return NULL;
}
static void* timesFooByTwo(int val)
{
printf("%d\n", (val * 2));
return NULL;
}
static void* mapFooToBar(double obj1, size_t obj2)
{
printf("foo(%f)->bar(%zu)\n", obj1, obj2);
return NULL;
}
int main(void)
{
void* (*functionSteps[NUM_STEPS])();
functionSteps[0] = (void*)filterEvenFoos;
functionSteps[1] = (void*)timesFooByTwo;
functionSteps[2] = (void*)mapFooToBar;
functionSteps[0]();
functionSteps[1](42);
functionSteps[2](3.14, &main);
return 0;
}
You could port it to C++ in many ways, but you could use the va_arg functionality to get variable inputs like so:
#include <iostream>
#include <cstdarg>
#include <vector>
static void* filterEvenFoos(int na, ...)
{
std::cout << 42 << std::endl;
return NULL;
}
static void* timesFooByTwo(int na, ...)
{
va_list vl;
va_start(vl, na);
std::cout << ((va_arg(vl, int)) * 2) << std::endl;
va_end(vl);
return NULL;
}
static void* mapFooToBar(int na, ...)
{
va_list vl;
va_start(vl, na);
double obj1 = va_arg(vl, double);
size_t obj2 = va_arg(vl, size_t);
std::cout << "foo(" << obj1 << ")->bar(" << obj2 << ")" << std::endl;
va_end(vl);
return NULL;
}
int main(int argc, char* argv[])
{
std::vector<void* (*)(int, ...)> functionSteps;
functionSteps.push_back(&filterEvenFoos);
functionSteps.push_back(×FooByTwo);
functionSteps.push_back(&mapFooToBar);
functionSteps[0](0);
functionSteps[1](0, 42);
functionSteps[2](0, 3.14, &main);
return 0;
}
You might note that the function signature changes slightly to allow a portable way to access the variadic arguments in each function.
If you're using C++11, you could also make use of the std::function inside the vector, but you still need to have matching function signatures.
You could also make use of classes and inheritance, or template specializations, but those could be extreme over-kill in your scenario.
In the end, it's not a direct port from the C code to C++, but it is doable.
Hope that can help.
It's possible, but the syntax is a bit dicey to get right. It's easier if you use a typedef for your callback-function-type, like this:
#include <stdio.h>
void* filterEvenFoos() {return NULL;}
void* timesFooByTwo() {return NULL;}
void* mapFooToBar() {return NULL;}
typedef void* (*VoidFunction)();
int main(int, char **)
{
const int numSteps = 3;
VoidFunction functionSteps[numSteps];
functionSteps[0] = filterEvenFoos;
functionSteps[1] = timesFooByTwo;
functionSteps[2] = mapFooToBar;
}
My function has the return type int.I want to return nothing in one case. using return NULL appears to be erroneous. what is to be used instead return NULL?
You cannot return nothing. You can only do that with pointer types. Even if you get it to compile, it will return 0, not nothing.
Since C++11 NULL can be either defined as an integral constant expression that evaluates to zero, or nullptr. If the latter is the case then your program is ill-formed as nullptr cannot be converted to int.
NULL is an obsolete macro used to express a null pointer constant in an idiomatic way. It doesn't represent an "empty" object. For that, other techniques like boost::optional are available.
However, that is most certainly not what you need, so just rethink your design and how to return a value that is outside the normal output range and indicates an empty return value. (E.g. -1.)
If you have a function like this:
int GetPrice (const char* product)
{
if (FindProduct (product)) {
return GetProduct (product)->price;
} else {
return NULL;
}
}
this won't do what you expect. Even if NULL is defined to NULL (as is for some older compilers), you will return the numeric value 0, so for people calling your function there will be no way to understand whether a product is free (price is 0) or the product was not found.
In C++, you can solve this for instance by using a reference:
bool GetPrice (const char* product, int& price)
{
if (FindProduct (product)) {
price = GetProduct (product)->price;
return true;
} else {
return false;
}
}
In a future standard, you may achieve what you want by using an optional value: http://en.cppreference.com/w/cpp/experimental/optional. You can easily mimic this by returning for instance a struct with a bool indicating whether the value was set.
I defined following two function macro to check exit flag in my thread class.
//use this in run()
#define CHECK_EXIT if( exitFlag_ ) {\
//do something\
return;\
}\
//use this in function
#define CHECK_EXIT_IN_FUNC if( exitFlag_ ) {\
//do something\
return false;\
}\
I had to define them separately because returning value is different.
Can I define it in one macro?
I googled, but couldn't find answer.
Thanks for any advice.
You can use a variadic macro. Pass in nothing if you don't want to return anything after the check.
#define CHECK_EXIT(...) CHECK_EXIT_(_, ##__VA_ARGS__)
#define CHECK_EXIT_(...) CHECK_EXIT_X(__VA_ARGS__, _1, _0)(__VA_ARGS__)
#define CHECK_EXIT_X(_0, _1, X, ...) CHECK_EXIT ## X
#define CHECK_EXIT_0(_) do if (exit_flag_) { /*...*/ return; } while(0)
#define CHECK_EXIT_1(_, R) do if (exit_flag_) { /*...*/ return (R); } while(0)
void test_0 () {
bool exit_flag_ = true;
CHECK_EXIT();
}
int test_1 () {
bool exit_flag_ = true;
CHECK_EXIT(0);
return 1;
}
I used a very simplified version of the argument counting trick described in a different answer. I am able to simplify it because I rely on a GCC extension (##__VA_ARGS__) to remove the trailing comma if the variable arguments expansion is empty. Use the full blown version if you are not using a compiler that understands this GCC extension.
I'm not sure how you can do it "in one macro" for functions of different types, unless you opt to specify the actual return value from outside.
If you don't mind doing that, then you can take advantage of the fact that in C++ (but not in C) you can return void expressions from void functions. For example, you can return (void) 0 as a "void" value. I.e. you can do
#define CHECK_EXIT_IN_FUNC(ret) if( exitFlag_ ) {\
//do something\
return (ret);\
}
and invoke it as CHECK_EXIT_IN_FUNC(false) or CHECK_EXIT_IN_FUNC((void) 0) depending on the type of the function.
The C++11 rules for return types create a bit of an interesting case:
A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function. The value of the expression is implicitly converted to the return type of the function in which it appears.
and later
A return statement with an expression of type void can be used only in functions with a return type of cv void; the expression is evaluated just before the function returns to its caller.
It seemed natural to create a type that would implicitly convert to void. Unfortunately the expression has this custom type, which counts as non-void type, and is rejected.
struct does_not_work
{
operator void() const {}
template<typename T> operator T() const { return T{}; }
};
I'm not sure whether I would support rewording the rule to allow types that implicitly convert to the return type even if that return type is void.
Similarly, this is rejected:
return {};
(but so is void{})
I would like to pass a pointer by reference to a function, such that i can actually change the address the passed pointer is pointing to and i'd like to assign this argument a default value.
something like this:
in the declaration
void myFunc(SomeType* &var=NULL);
and the definition:
void MyClass::myFunc(SomeType* &var){
if(var!=NULL)
(*var)=(*someOtherPointer);
if(someCondition)
var=NULL;
}
such that a callee can decide whether he wants to call the function with one argument or without argument. And sucht that if he decides to pass an argument, and someCondition holds, the passed pointer will point to NULL afterwards
however - if i try to do it like this i get a:
Error C2440: 'default argument': 'int' cannot be conveted to 'SomeType *&'
Thanks for the help!
NULL is not an lvalue - it cannot be passed by reference. It would be like passing 4 to a function that expects an int&.
The 'int' part is because NULL is a macro - defined 0.
Your best bet would be using a pointer to pass the pointer by reference, i.e. a double pointer. Then, if the parameter is NULL, nothing was passed. If not, it's the address of the pointer that should be modified [to point to NULL if someCondition holds].
The error message says it all: you are passing an integer instead of a reference-to-a-pointer-to-SomeType. To do what you want, you can use a pointer-to-a-pointer-to-SomeType:
void myFunc(SomeType** var=NULL);
void MyClass::myFunc(SomeType** var){
if(var!=NULL && *var!=NULL)
(**var)=(*someOtherPointer);
if(var!=NULL && someCondition)
*var=NULL;
}
You can also consider using boost::optional (not the simplest code you can use, but the option is there):
void f( boost::optional<int&> r = boost::optional<int&>() )
{
if ( r ) *r = 5;
}
int main()
{
int x = 0;
f( x ); std::cout << x << std::endl; // 5, it did change the value
f(); // compiler will default to an empty optional<int&> object
}
Ok, I can see why you'd do this from the perspective of exercising the C++ brain, but would you really do that in production code? It looks like an incredibly misty technique with side effects, when looking at the code as a colleague 1 year later. Did you think of using two separate functions with clear names, one returning a pointer and one doing any other needed work?
Why not just overload the function?
void myFunc() {
//whatever logic should happen if a null pointer is passed in
}
void myFunc(SomeType* &var) {
if(var!=NULL) {
(*var)=(*someOtherPointer);
}
if(someCondition) {
var=NULL;
}
}