Best way to write a constructor that could have invalid parameters
I have a question about writing readable and efficient code in C++.
I’m creating a class for tcp connections with a constructor that takes as input the IP of the server and the port. I would like to avoid the creation of the object if for example the IP is wrong.
My question is:
Is it better to throw an exception in case of a failure or create a
wrapper class with a Boolean to check if the internal object was
created correctly and avoid calling any functions in case of failure?
c++ code-readability
add a comment |
I have a question about writing readable and efficient code in C++.
I’m creating a class for tcp connections with a constructor that takes as input the IP of the server and the port. I would like to avoid the creation of the object if for example the IP is wrong.
My question is:
Is it better to throw an exception in case of a failure or create a
wrapper class with a Boolean to check if the internal object was
created correctly and avoid calling any functions in case of failure?
c++ code-readability
4
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
2
a function that returns astd::optional<connection>
if you can use c++17
– user463035818
Nov 22 '18 at 13:50
1
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54
add a comment |
I have a question about writing readable and efficient code in C++.
I’m creating a class for tcp connections with a constructor that takes as input the IP of the server and the port. I would like to avoid the creation of the object if for example the IP is wrong.
My question is:
Is it better to throw an exception in case of a failure or create a
wrapper class with a Boolean to check if the internal object was
created correctly and avoid calling any functions in case of failure?
c++ code-readability
I have a question about writing readable and efficient code in C++.
I’m creating a class for tcp connections with a constructor that takes as input the IP of the server and the port. I would like to avoid the creation of the object if for example the IP is wrong.
My question is:
Is it better to throw an exception in case of a failure or create a
wrapper class with a Boolean to check if the internal object was
created correctly and avoid calling any functions in case of failure?
c++ code-readability
c++ code-readability
edited Nov 22 '18 at 15:29
scipsycho
1438
1438
asked Nov 22 '18 at 13:44
Matteo CultreraMatteo Cultrera
2311
2311
4
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
2
a function that returns astd::optional<connection>
if you can use c++17
– user463035818
Nov 22 '18 at 13:50
1
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54
add a comment |
4
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
2
a function that returns astd::optional<connection>
if you can use c++17
– user463035818
Nov 22 '18 at 13:50
1
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54
4
4
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
2
2
a function that returns a
std::optional<connection>
if you can use c++17– user463035818
Nov 22 '18 at 13:50
a function that returns a
std::optional<connection>
if you can use c++17– user463035818
Nov 22 '18 at 13:50
1
1
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54
add a comment |
1 Answer
1
active
oldest
votes
Throwing in a constructor upon invalid input is fine and even recommend by the core guidelines.
Named constructors (i.e. static member functions) are an equally valid approach, they could e.g. return a std::optional<YourType>
(C++17 is required, then). This makes it obvious that the instantiation could fail and circumvents the drawbacks of exceptions. Here's a small example.
#include <optional>
class Example {
public:
static std::optional<Example> validateAndCreate(...);
private:
/* Private ctor makes usage of the above function mandatory. */
Example(...);
};
And an implementation of the creation method could be
std::optional<Example> validateAndCreate(...)
{
/* Use e.g. some utility function for validation: */
if (isInputValid(/* Pass parameter. */))
return Example(/* Pass parameter. */);
else
return std::nullopt;
}
where client code then constructors objects like this:
if (const auto instance = Example::validateAndCreate())
/* Do stuff with the instance. */
;
else
std::cerr << "What now?n";
I guess this approach is more self-documenting (the fact that a ctor might throw should be documented somewhere), but also more verbose.
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
No,std::optional
owns its data and does not allocate. It's like the ordinary return value plus abool
ean flag.
– lubgr
Nov 22 '18 at 14:10
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432365%2fbest-way-to-write-a-constructor-that-could-have-invalid-parameters%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Throwing in a constructor upon invalid input is fine and even recommend by the core guidelines.
Named constructors (i.e. static member functions) are an equally valid approach, they could e.g. return a std::optional<YourType>
(C++17 is required, then). This makes it obvious that the instantiation could fail and circumvents the drawbacks of exceptions. Here's a small example.
#include <optional>
class Example {
public:
static std::optional<Example> validateAndCreate(...);
private:
/* Private ctor makes usage of the above function mandatory. */
Example(...);
};
And an implementation of the creation method could be
std::optional<Example> validateAndCreate(...)
{
/* Use e.g. some utility function for validation: */
if (isInputValid(/* Pass parameter. */))
return Example(/* Pass parameter. */);
else
return std::nullopt;
}
where client code then constructors objects like this:
if (const auto instance = Example::validateAndCreate())
/* Do stuff with the instance. */
;
else
std::cerr << "What now?n";
I guess this approach is more self-documenting (the fact that a ctor might throw should be documented somewhere), but also more verbose.
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
No,std::optional
owns its data and does not allocate. It's like the ordinary return value plus abool
ean flag.
– lubgr
Nov 22 '18 at 14:10
add a comment |
Throwing in a constructor upon invalid input is fine and even recommend by the core guidelines.
Named constructors (i.e. static member functions) are an equally valid approach, they could e.g. return a std::optional<YourType>
(C++17 is required, then). This makes it obvious that the instantiation could fail and circumvents the drawbacks of exceptions. Here's a small example.
#include <optional>
class Example {
public:
static std::optional<Example> validateAndCreate(...);
private:
/* Private ctor makes usage of the above function mandatory. */
Example(...);
};
And an implementation of the creation method could be
std::optional<Example> validateAndCreate(...)
{
/* Use e.g. some utility function for validation: */
if (isInputValid(/* Pass parameter. */))
return Example(/* Pass parameter. */);
else
return std::nullopt;
}
where client code then constructors objects like this:
if (const auto instance = Example::validateAndCreate())
/* Do stuff with the instance. */
;
else
std::cerr << "What now?n";
I guess this approach is more self-documenting (the fact that a ctor might throw should be documented somewhere), but also more verbose.
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
No,std::optional
owns its data and does not allocate. It's like the ordinary return value plus abool
ean flag.
– lubgr
Nov 22 '18 at 14:10
add a comment |
Throwing in a constructor upon invalid input is fine and even recommend by the core guidelines.
Named constructors (i.e. static member functions) are an equally valid approach, they could e.g. return a std::optional<YourType>
(C++17 is required, then). This makes it obvious that the instantiation could fail and circumvents the drawbacks of exceptions. Here's a small example.
#include <optional>
class Example {
public:
static std::optional<Example> validateAndCreate(...);
private:
/* Private ctor makes usage of the above function mandatory. */
Example(...);
};
And an implementation of the creation method could be
std::optional<Example> validateAndCreate(...)
{
/* Use e.g. some utility function for validation: */
if (isInputValid(/* Pass parameter. */))
return Example(/* Pass parameter. */);
else
return std::nullopt;
}
where client code then constructors objects like this:
if (const auto instance = Example::validateAndCreate())
/* Do stuff with the instance. */
;
else
std::cerr << "What now?n";
I guess this approach is more self-documenting (the fact that a ctor might throw should be documented somewhere), but also more verbose.
Throwing in a constructor upon invalid input is fine and even recommend by the core guidelines.
Named constructors (i.e. static member functions) are an equally valid approach, they could e.g. return a std::optional<YourType>
(C++17 is required, then). This makes it obvious that the instantiation could fail and circumvents the drawbacks of exceptions. Here's a small example.
#include <optional>
class Example {
public:
static std::optional<Example> validateAndCreate(...);
private:
/* Private ctor makes usage of the above function mandatory. */
Example(...);
};
And an implementation of the creation method could be
std::optional<Example> validateAndCreate(...)
{
/* Use e.g. some utility function for validation: */
if (isInputValid(/* Pass parameter. */))
return Example(/* Pass parameter. */);
else
return std::nullopt;
}
where client code then constructors objects like this:
if (const auto instance = Example::validateAndCreate())
/* Do stuff with the instance. */
;
else
std::cerr << "What now?n";
I guess this approach is more self-documenting (the fact that a ctor might throw should be documented somewhere), but also more verbose.
answered Nov 22 '18 at 13:51


lubgrlubgr
12.7k21847
12.7k21847
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
No,std::optional
owns its data and does not allocate. It's like the ordinary return value plus abool
ean flag.
– lubgr
Nov 22 '18 at 14:10
add a comment |
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
No,std::optional
owns its data and does not allocate. It's like the ordinary return value plus abool
ean flag.
– lubgr
Nov 22 '18 at 14:10
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
interesting method indeed. Just one question, does that mean that the variable is always allocated dynamically??
– scipsycho
Nov 22 '18 at 14:08
1
1
No,
std::optional
owns its data and does not allocate. It's like the ordinary return value plus a bool
ean flag.– lubgr
Nov 22 '18 at 14:10
No,
std::optional
owns its data and does not allocate. It's like the ordinary return value plus a bool
ean flag.– lubgr
Nov 22 '18 at 14:10
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53432365%2fbest-way-to-write-a-constructor-that-could-have-invalid-parameters%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
The "standard" answer to your question. Or you can use factory pattern.
– felix
Nov 22 '18 at 13:46
2
a function that returns a
std::optional<connection>
if you can use c++17– user463035818
Nov 22 '18 at 13:50
1
You can also follow wg21.link/p0323 for a possible future option.
– StoryTeller
Nov 22 '18 at 13:54