I was wondering if there's an elegant solution for the following issue:
Let's say I'd like to have a variable holding a value with a pretty complex type and would the compiler to automatically infer it's type, but declare first and give value later in the code because of initialization in an if statement.
For example:
{
auto a;
if (some predicate)
a = init_a(1);
else
a = init_a(2);
}
Obviously this code doesn't compile, but the I think that the compiler has all the information it needs to infer the type.
If 'a' was just an int, this was not a problem, but if the type is a complex template, I don't want to have to write it (or in some cases even know it).
Also, i wouldn't want to call the default constructor of a and then write over it.
Possible solutions:
Template the type of 'a'.
initialize 'a' using a lambda and move the predicate into the lambda.
Just write the type of 'a' instead auto.
Use a void pointer/shared_ptr and then init 'a' on the heap.
Each of these has its own drawbacks.
Is there a more elegant solution for it?
The compiler doesn't have infinite lookahead what is happening further on in the code. It only knows what's happening at the current statement. Therefore it can't deduce any types without an initializer.
If you don't know the return-type of init_a then you could use decltype:
decltype(init_a(1)) a;
You can also use a lambda call to initialize the variable:
auto a = [ /* Captures needed for the condition... */ ]()
{
if (some_condition)
return init_a(1);
else
return init_a(2);
}(); // Call the lambda immediately
Or, as mentioned in many comments, use the ternary conditional expression:
auto a = some_condition ? init_a(1) : init_a(2);
There's a technique called "Immediately Invoked Lambda Expression" that is using lambda to initialize a variable in a complex way. Using this approach your a can be const which improves const-correctness. More details here.
For a simple binary predicate, consider just using the ternary operator:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = somePredicate(input) ? initA(1) : initA(2);
}
for more complex initialization logic (beyond a binary case), wrap the initialization logic in a lambda:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = []() {
if (somePredicate(input)) { return initA(1); }
else if (input == 100) { return initA(100); }
else { return initA(2); }}();
}
Both these approaches come with additional possibility of making the variable to be initialized const.
If the return types of your lambda are different but convertible to some type then you can force the return type (note the -> is mandatory when specifying a return type):
auto a = [=]() -> ConvertedType {
if (some_predicate) {
return CovertibleType1(1);
} else if (other_predicate) {
return ConvertibleType2(2);
}
return ConvertibleType3(3);
}();
Though I realize this basically defeats the auto declaration...
Related
The full context of this problem is unfortunately too involved to explain, but suffice to say it involves some complicated template metaprogramming and I find myself having to do some funny things. I've tried to boil down an issue I've encountered into a minimal example, so the question may seem awkward. If it's possible to do this I'd be interested to know how, if not I'd be interested in hearing possible alternatives.
I'd like to create a function that takes as input a lambda function that may return void or something else. If it does return void, I'd like to convert it into an identical lambda that, instead of returning void, returns true.
template <typename InputFuncType>
auto function_converter(InputFuncType lambda_func)
{
// I also need to figure out how to deduce the return type of lambda_func
// might be something like this.
if constexpr (std::is_same<std::result_of<InputFuncType>::type, void>::value)
{
// Current best guess. Note that in the context of the converter, I don't explicitly know
// lambda_func's input type, so I'm not sure how to do something like this.
return [](InputFuncType::input_args_t... args) {lambda_func(args); return true;};
}
return lambda_func;
}
// target usage
const auto lam1 = [](int a) {return;};
const auto lam2 = function_converter(lam1);
int x = 4;
lam1(x); // returns void
const bool y2 = lam2(x); // returns true
I'm using c++17.
A little redundant, I suppose, but the following wrapper should works
template <typename InputFuncType>
auto function_converter (InputFuncType lf)
{
return [=](auto && ... args)
{
using RT = decltype(lf(std::forward<decltype(args)>(args)...));
if constexpr ( true == std::is_same_v<void, RT> )
{
lf(std::forward<decltype(args)>(args)...);
return true;
}
else
return lf(std::forward<decltype(args)>(args)...);
};
}
Substantially, the idea is transfer the check, about the returned type, inside the internal lambda.
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
I'm new to C++, and am used to working with Java.
In Java, I have the option of declaring an object without instantiating it, and would like to do the same in C++.
Assuming there is some class Foo, in Java I could write Foo bar; to declare an instance of Foo without initializing bar.
However, in C++ when I write Foo bar;, bar is initialized by calling the default constructor of class Foo.
This is particularly vexing if I have written one or more constructors for class Foo, each of which have at least one argument. In this case, the code will fail to compile with an error similar to no matching function for call to 'Foo::Foo()'
For example, say I have the following class definition in Java:
public class Foo {
private boolean b;
Foo(boolean b) { this.b = b; }
}
and the corresponding class definition in C++:
class Foo {
bool b_;
public:
Foo(bool b) : b_(b) {}
};
In Java, I could write some method
public static Foo makeFoo(int x) {
Foo result;
if (x > 10) { result = new Foo(true); }
else { result = new Foo(false); }
return result;
}
However, if I write a similar method in C++, I get a compilation error:
Foo makeFoo(int x) {
Foo result; // here, a call is made to Foo::Foo() which doesn't exist, and thus compilation fails
if (x > 10) {
result = Foo(true); // this would probably also fail since I didn't specify a copy-constructor, but I'm not entirely sure
}
else {
result = Foo(false); // as above, I think this would probably fail
}
return result;
}
While the example I gave is useless, I frequently used this sort of approach when writing Java code.
Is there a way to emulate this behavior in C++?
Alternatively, is this just bad design? If so, what sort of approach would you recommend?
If you don't want to use pointers to get reference functionality as Igor (and others) explained in the first comment on your question, then you can do a couple of things.
First, the philosophy of value types instead of reference types is do not create them until you need them. Your temptation to declare the reference ahead of using the object to obtain a sort of polymorphic functionality in the remainder of the function (some post-create common init code, perhaps) is reasonable design, but cannot be expressed the way you wrote it because it would involve creating a value.
You could provide a default constructor and give it some behaviour -- but it's pretty clear that neither you nor anybody else want to be coerced into doing that.
The essence of the alternative is to move the variable inside the scope and return it.
Foo makeFoo(int x) {
if (x > 10) {
Foo result = Foo(true);
return result;
}
else {
Foo result = Foo(false);
return result;
}
}
Obviously this prevents you from writing common post-create init code after the if block before the return. To do that, you would write the if block in its own function and have it return the result, then write the follow up code after you've initialized your object.
Foo premakeFoo(int x) {
if (x > 10) {
Foo result = Foo(true);
return result;
}
else {
Foo result = Foo(false);
return result;
}
}
Foo makeFoo(int x) {
Foo result = premakeFoo(x);
// common post init code can go here.
return result;
}
If you don't want it in a completely separate function, you could do a lambda.
Foo makeFoo(int x) {
Foo result = ([=]() {
if (x > 10) {
Foo result = Foo(true);
return result;
} else {
Foo result = Foo(false);
return result;
}
})();
// common post init code can go here.
return result;
}
Or in your case, if it's small, use a ternary expression inline.
Foo makeFoo(int x) {
Foo result = (x > 10) ? Foo(true) : Foo(false); // or just Foo(x>10)
// common post init code can go here.
return result;
}
There are other clever options involving templates, but they all revolve around the idea of isolating the different expressions for the overloaded constructors and then using an assignment to initialize a variable given some more sophisticated expression. And what you are trying to do is to get the expression that constructs the value in two different ways to span a scope block (span the if blocks). Ternaries and functions are the options here for getting the if logic executed within a single expression.
In Java when you do Foo result; you create a reference to Foo, you don't actually create an object. C++ is different though since it has value semantics and Foo result; actually creates an object. If there is no default constructor, then an error is raised.
To get the same type of behavior you need to use pointers in C++. You can't use a reference since a reference needs to be bound to an object when it is created, unlike Java. So, if you use a std::unique_ptr<Foo> you can declare that, and then initialize it later with a std::unique_ptr<Foo> that you initialize in your creation logic. Using your example, the code would look like
Foo makeFoo(int x) {
std::unique_ptr<Foo> result; // here result doesn't have an actual object yet
if (x > 10) {
result = std::make_unique<Foo>(true); // now we pass the values we want to construct with and get a valid object
}
else {
result = std::make_unique<Foo>(false); // same as above
}
return *result; // this lets you return a `Foo` which will be a copy, and the Foo created by make_unique will be destroyed
}
If you don't want to make a copy, you can use return result; instead, and change the function to return a std::unique_ptr<Foo>.
what you are trying to do is called a factory pattern and is usually implemented in this way
std::unique_ptr<Foo> makeFoo(int x) {
std::unique_ptr<Foo> result = nullptr;
if (x > 10) {
result = std::make_unique<Foo>(true);
}
else {
result = std::make_unique<Foo>(false);
}
return result;
}
for the above to work you also need to include the header. refer to this for further information on unique_ptr and memory management in c++
also, note I would not recommend this level of verbosity in code, I wrote that out for presentation purposes. The following version offers fewer lines of code and is more elegant.
std::unique_ptr<Foo> makeFoo(int x) {
if (x > 10) {
return std::make_unique<Foo>(true);
}
return std::make_unique<Foo>(false);
}
I want to know, how to create a pointer that points to the address of a function.
Supose that we have the following function:
int doublex(int a)
{
return a*2;
}
I already know that & is used to get the address. How could I point to this function?
As said, you can just take the address with the & operator. Then the easiest way is to assign it with a auto variable to store it, now you can use your variable like a function itself.
int doubleNumber(int x)
{
return x*2;
}
int main()
{
auto func = &doubleNumber;
std::cout << func(3);
}
See a live example here
Just do:
auto function_pointer = &doublex;
And what is the auto type?
The auto keyword specifies that the type of the variable that is being declared will be automatically deducted from its initializer. In case of functions, if their return type is auto then that will be evaluated by return type expression at runtime. Source here
This will help you: C++ auto keyword. Why is it magic?
You can do something like this and store references to compatible functions or pass your function as parameter in another function.
typedef int (*my_function_type)(int a);
int double_number(int a)
{
return a*2;
}
my_function_type my_function_pointer = double_number;
int transform_number(int target, my_function_type transform_function) {
return transform_function(target);
}
I hope it helps you
Background
I have a series of lambdas that perform different checks on the captured variables and return std::nullopt if the check failed. return std::nullopt is the first return statement. Then, if the check succeeded, they go on and compute the value.
Problem
The types of return expressions are not consistent, e.g. std::nullopt_t cannot be converted to std::optional<T>, even though the other way around works. In particular, I'd like the following code to compile and run, printing 2:
#include <functional>
#include <utility>
#include <optional>
int x = 3;
auto lambda = [](){
if (x == 2)
return std::nullopt;
return std::optional(2);
};
#include <iostream>
int main () {
using return_type = std::invoke_result_t<decltype(lambda)>;
static_assert(std::is_same<return_type, std::optional<int>>{},
"return type is still std::nullopt_t");
std::cout << lambda().value() << '\n';
}
Wandbox Demo.
Thoughts
I believe that I need to use std::common_type<Args...> somewhere, but I can neither enforce presence of it or deduce Args, as it might require language support.
Instead of using template type deduction to infer the return type of the lambda, why not explicitly specify that return type?
auto lambda = []() -> std::optional<int> {
if (x == 2)
return std::nullopt;
return 2;
};
std::common_type is commonly with templates, which you don't have.
I suggest to stick with a single return statement and explicitly specified result type without using nullopt at all. It looks somewhat misleading when a function returns either an integer or a nullopt. Especially if the function was longer. Also if value type was something with an explicit constructor then use of emplace allows to avoid typing value type name again.
auto lambda = []()
{
std::optional<int> result{};
if(2 != x)
{
result.emplace(2);
}
return result;
};