Best way to write a constructor that could have invalid parameters












0















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?











share|improve this question




















  • 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
















0















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?











share|improve this question




















  • 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














0












0








0








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?











share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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














  • 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








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












1 Answer
1






active

oldest

votes


















3














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.






share|improve this answer
























  • 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 a boolean flag.

    – lubgr
    Nov 22 '18 at 14:10











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
});


}
});














draft saved

draft discarded


















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









3














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.






share|improve this answer
























  • 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 a boolean flag.

    – lubgr
    Nov 22 '18 at 14:10
















3














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.






share|improve this answer
























  • 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 a boolean flag.

    – lubgr
    Nov 22 '18 at 14:10














3












3








3







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.






share|improve this answer













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.







share|improve this answer












share|improve this answer



share|improve this answer










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 a boolean 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






  • 1





    No, std::optional owns its data and does not allocate. It's like the ordinary return value plus a boolean 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 boolean 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 boolean flag.

– lubgr
Nov 22 '18 at 14:10




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith