(The root problem here is that I'm trying to use decltype
, or some other type deduction perhaps based on auto
, on complicated expressions that involve lambdas. I'm trying to find some sort of workaround. I've been playing around with http://pfultz2.github.com/Pythy/ for polymorphic lambdas. I can't fully go into the motivation without telling you all a long story! )
I want to be able to do decltype([](int){return 3.5L};
to get the type of the lambda, or at least the return type. Yes, I know that lambdas are given a unique type, I don't need to be reminded that decltype([](int){return 3.5L};
will give two different types if used on two different lines.
If I use decltype
on a lambda, then I get an error message ('lambda used in unevaluated context'). I know that seems like a reasonable error message, but I'm surprised at C++ holding my hand like that! It would be useful to be allowed to do this, in particular to access the return type of the lambda. Is this error simply a result of overzealous error messages, or is there truly a good reason why it can't be done?
An expression such as this works inside a member function:
template<typename T>
struct X {
void foo() {
static auto l = [](int){return 3.5;};
}
};
but I'm not allowed to do:
template<typename T>
struct X {
static auto var = [](int){return 3.5;}; // will also fail if I use constexpr here
};
x.cpp:8:47: error: expression ‘#‘lambda_expr’ not supported by
dump_expr#<expression error>’ is not a constant-expression
x.cpp:8:47: error: unable to deduce ‘const auto’ from ‘<expression error>’
This inspired my idea to try to use a static variable in a function in order to do the type inference on the lambda.
This seems to work a little better if X is not a template. But I need X to be a template - in particular, the arguments to the lambda will take the type of the template parameters.
Remember, I only want the type of the lambda, and I would be satisfied only with the return type. It's frustrating that the compiler is willing and able to do type inference, and static initialization, in both cases, but it seems to put some arbitrary obstacles in my way.
Can I access the type of the variable var_in_func
from outside the dummy_func
function?
struct S {
constexpr static auto member = a_complicated_expression... // error
void dummy_func() {
static auto var_in_func = a_complicated_expression... // OK
}
typedef dummy_func :: var_in_func the_type; // I'd like this to work
};
If there are lambdas in a_complicated_expression...
, there is often a problem with the initializer for member
. If S
is actually a struct template, then I get error messages that member
has no initializer. That's why I'm trying to find other ways around this.
However, the static auto
variable inside the static method dummy_func
works fine. So that got me thinking that they ought to be a nice way to access the type of that static variable?
I tried the following but it didn't work because dummy_func
isn't a type (fair enough):
typedef dummy_fun :: var_in_func the_type_of_the_static_variable_in_the_method;
I can't do decltype( a_complicated_expression... )
as the compiler complains about the use of a lambda in an unevaluated context (a declspec).
I'm using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
. I don't mind if I have to use g++ specific extensions.
If a static variable is defined outside of the functions it will be accessible only by the code that follows in the file it is declared. If the static variable is declared in a function, it will only be accessible from the function, and it will keep its value between function executions.
Static variables can be accessed by calling with the class name ClassName. VariableName. When declaring class variables as public static final, then variable names (constants) are all in upper case. If the static variables are not public and final, the naming syntax is the same as instance and local variables.
So, the benefit of using a static variable as a global variable is that it can be accessed from anywhere inside the program since it is declared globally. Below is the code which shows how it is declared.
By using static variables a single copy is shared among all the instances of the class, and they can be accessed directly by class name and don't require any instance. The Static method similarly belongs to the class and not the instance and it can access only static variables but not non-static variables.
Non-capturing lambdas can be converted to a function pointer, and have an operator()
with the signature of that function pointer:
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...)) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) const) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) volatile) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) const volatile) -> R(*)(Args...);
template<typename T>
auto to_f_ptr(T t) -> decltype(remove_class(&T::operator())) { return t; }
You can now write auto var = to_f_ptr([](int){return 3.5;});
and var
will have type double (*)(int)
.
However, you still won't be able to use the lambda as a class-scope static
initialiser; see lambda as a static member.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With