0

Wanted your opinion on which way will be better. Below is a sample code where I have used std::optional in the argument of a lambda and the lambda itself is an argument of the class constructor.

OPTION 1
struct PrintSettings {
 bool is_double_sided;
 bool is_color;
 int num_copies;
};
class Printer {
public:
 Printer(std::function<void(std::optional<PrintSettings>)>&& printFunction)
 : printFunction_(std::move(printFunction)) {
 }
 void print() {
 printFunction_(std::nullopt);
 }
 void printWithSettings(const PrintSettings& settings) {
 printFunction_(settings);
 }
private:
 std::function<void(std::optional<PrintSettings>)> printFunction_;
};
int main() {
 const PrintSettings defaultSettings{false, true, 1};
 auto printer = std::make_unique<Printer>(
 [defaultSettings] (std::optional<PrintSettings> settings) {
 const PrintSettings printSettings = settings.value_or(defaultSettings);
 std::cout << "Double sided: " << printSettings.is_double_sided << "\n";
 std::cout << "Color: " << printSettings.is_color << "\n";
 std::cout << "Number of copies: " << printSettings.num_copies << "\n";
 });
 printer->print();
 const PrintSettings someSettings{true, false, 2};
 printer->printWithSettings(someSettings);
 return 0;
}

Now I understand that instead of using std::optional I can directly put the argument as non-optional in the lambda and then from the function print()(which takes no settings) i can create a default settings argument which will be static const and pass that as the lambda argument as shown below:-

OPTION 2
struct PrintSettings {
 bool is_double_sided;
 bool is_color;
 int num_copies;
};
class Printer {
public:
 Printer(std::function<void(const PrintSettings&)>&& printFunction)
 : printFunction_(std::move(printFunction)) {
 }
 void print() {
 static const PrintSettings defaultSettings{false, true, 1};
 printFunction_(defaultSettings);
 }
 void printWithSettings(const PrintSettings& settings) {
 printFunction_(settings);
 }
private:
 std::function<void(const PrintSettings&)> printFunction_;
};
int main() {
 auto printer = std::make_unique<Printer>(
 [] (const PrintSettings& settings) {
 std::cout << "Double sided: " << settings.is_double_sided << "\n";
 std::cout << "Color: " << settings.is_color << "\n";
 std::cout << "Number of copies: " << settings.num_copies << "\n";
 });
 printer->print();
 const PrintSettings someSettings{true, false, 2};
 printer->printWithSettings(someSettings);
 return 0;
}

I wanted to ask which option will be better in terms of complexities and readability. I understand there is a boolean overhead to std::optional as well. Please note that printWithSettings() is a newer version of print() and we are keeping print() only for backward compatibility.

asked May 2, 2024 at 9:55
1
  • Instead of deleting / re-posting, you can also flag the question for moderator attention and ask them if they can migrate the question. Commented May 2, 2024 at 12:14

2 Answers 2

4

In your example, the location in code where the default value "lives" is quite different:

  • in the first case, the printFunction itself (or the code which composes this function) has to know about the defaultSettings.

  • in the second case, the defaultSettings are defined at the level of the code which calls the printFunction, which is here the Printer class.

In this simplified example, this may appear not as a huge difference. In a real world program, however, the printFunction and the Printer class may live in completely different layers or may be under maintenance of completely different people or organizations. Hence the decision criteria should be in which layer or by whom you want the defaultSettings to be maintained.

answered May 2, 2024 at 12:34
-3

"optional" should be used for things that are genuinely not there, and not for default values. So if it is possible that there are no print settings, make it optional. If you decided to use default values, you can put defaults into your parameter list, are pass them directly.

answered May 2, 2024 at 10:58
2
  • 3
    I am a little bit nitty here, of course, but I think optional should be used for things that may be there or not, not for things which are not there. Commented May 2, 2024 at 12:02
  • 1
    Ok, I looked it up on Stackoverflow - which says at least in C++11, this answer isn't really helpful, since lambdas don't support default parameters. Commented May 2, 2024 at 12:20

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.