Multiple return type from function - C++











up vote
-1
down vote

favorite
1












Is there any way (conventional or no) to get a choice between multiple specified return types from a function. For example:



/* Concept code... */
class var {
public:
union {
bool _bool;
int _int;
char* _char_pointer;
} primitive_value;
std::string type;

var(bool arg) { primitive_value._bool = arg; type = "bool"; }
var(int arg) { primitive_value._int = arg; type = "int"; }
var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }

// Function/ method that could return `bool`, `int` or `char*`
<bool, int, char*> valueOf() const {
if (type == "bool") return primitive_value._bool;
else if (type == "int") return primitive_value._int;
else if (type == "char*") return primitive_value._char_pointer;
}
};


There is a reference to a similar question here I've seen that suggested using void* pointers or union's but I have yet to fully understand how those work.



No container types (such as std::any, std::optional, std::variant) are allowed because I want to know if there is an alternative to those as well.



To add on, this is all in the name of curiosity. Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far.



I'm hoping the platform here could have a practical solution to this potential problem.










share|improve this question




















  • 8




    std::variant just does what you are asking. you could implement it yourself if you really want
    – M.M
    Nov 19 at 12:34








  • 6




    The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
    – Some programmer dude
    Nov 19 at 12:34






  • 2




    how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
    – user463035818
    Nov 19 at 12:37






  • 2




    See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
    – palotasb
    Nov 19 at 12:44






  • 1




    the problem is that you can't compare strings at compile time
    – Stack Danny
    Nov 19 at 12:59















up vote
-1
down vote

favorite
1












Is there any way (conventional or no) to get a choice between multiple specified return types from a function. For example:



/* Concept code... */
class var {
public:
union {
bool _bool;
int _int;
char* _char_pointer;
} primitive_value;
std::string type;

var(bool arg) { primitive_value._bool = arg; type = "bool"; }
var(int arg) { primitive_value._int = arg; type = "int"; }
var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }

// Function/ method that could return `bool`, `int` or `char*`
<bool, int, char*> valueOf() const {
if (type == "bool") return primitive_value._bool;
else if (type == "int") return primitive_value._int;
else if (type == "char*") return primitive_value._char_pointer;
}
};


There is a reference to a similar question here I've seen that suggested using void* pointers or union's but I have yet to fully understand how those work.



No container types (such as std::any, std::optional, std::variant) are allowed because I want to know if there is an alternative to those as well.



To add on, this is all in the name of curiosity. Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far.



I'm hoping the platform here could have a practical solution to this potential problem.










share|improve this question




















  • 8




    std::variant just does what you are asking. you could implement it yourself if you really want
    – M.M
    Nov 19 at 12:34








  • 6




    The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
    – Some programmer dude
    Nov 19 at 12:34






  • 2




    how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
    – user463035818
    Nov 19 at 12:37






  • 2




    See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
    – palotasb
    Nov 19 at 12:44






  • 1




    the problem is that you can't compare strings at compile time
    – Stack Danny
    Nov 19 at 12:59













up vote
-1
down vote

favorite
1









up vote
-1
down vote

favorite
1






1





Is there any way (conventional or no) to get a choice between multiple specified return types from a function. For example:



/* Concept code... */
class var {
public:
union {
bool _bool;
int _int;
char* _char_pointer;
} primitive_value;
std::string type;

var(bool arg) { primitive_value._bool = arg; type = "bool"; }
var(int arg) { primitive_value._int = arg; type = "int"; }
var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }

// Function/ method that could return `bool`, `int` or `char*`
<bool, int, char*> valueOf() const {
if (type == "bool") return primitive_value._bool;
else if (type == "int") return primitive_value._int;
else if (type == "char*") return primitive_value._char_pointer;
}
};


There is a reference to a similar question here I've seen that suggested using void* pointers or union's but I have yet to fully understand how those work.



No container types (such as std::any, std::optional, std::variant) are allowed because I want to know if there is an alternative to those as well.



To add on, this is all in the name of curiosity. Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far.



I'm hoping the platform here could have a practical solution to this potential problem.










share|improve this question















Is there any way (conventional or no) to get a choice between multiple specified return types from a function. For example:



/* Concept code... */
class var {
public:
union {
bool _bool;
int _int;
char* _char_pointer;
} primitive_value;
std::string type;

var(bool arg) { primitive_value._bool = arg; type = "bool"; }
var(int arg) { primitive_value._int = arg; type = "int"; }
var(char* arg) { primitive_value._char_pointer = arg; type = "char*"; }

// Function/ method that could return `bool`, `int` or `char*`
<bool, int, char*> valueOf() const {
if (type == "bool") return primitive_value._bool;
else if (type == "int") return primitive_value._int;
else if (type == "char*") return primitive_value._char_pointer;
}
};


There is a reference to a similar question here I've seen that suggested using void* pointers or union's but I have yet to fully understand how those work.



No container types (such as std::any, std::optional, std::variant) are allowed because I want to know if there is an alternative to those as well.



To add on, this is all in the name of curiosity. Currently I am searching the optional and variant header files to know how the feature I'm asking for was implemented but no luck so far.



I'm hoping the platform here could have a practical solution to this potential problem.







c++ c++17






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 19 at 13:06

























asked Nov 19 at 12:32









Lapys

396313




396313








  • 8




    std::variant just does what you are asking. you could implement it yourself if you really want
    – M.M
    Nov 19 at 12:34








  • 6




    The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
    – Some programmer dude
    Nov 19 at 12:34






  • 2




    how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
    – user463035818
    Nov 19 at 12:37






  • 2




    See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
    – palotasb
    Nov 19 at 12:44






  • 1




    the problem is that you can't compare strings at compile time
    – Stack Danny
    Nov 19 at 12:59














  • 8




    std::variant just does what you are asking. you could implement it yourself if you really want
    – M.M
    Nov 19 at 12:34








  • 6




    The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
    – Some programmer dude
    Nov 19 at 12:34






  • 2




    how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
    – user463035818
    Nov 19 at 12:37






  • 2




    See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
    – palotasb
    Nov 19 at 12:44






  • 1




    the problem is that you can't compare strings at compile time
    – Stack Danny
    Nov 19 at 12:59








8




8




std::variant just does what you are asking. you could implement it yourself if you really want
– M.M
Nov 19 at 12:34






std::variant just does what you are asking. you could implement it yourself if you really want
– M.M
Nov 19 at 12:34






6




6




The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
– Some programmer dude
Nov 19 at 12:34




The example code you show looks like a bad design. And why can't you use e.g. std::any or std::variant? How about templates (possibly with specialization)?
– Some programmer dude
Nov 19 at 12:34




2




2




how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
– user463035818
Nov 19 at 12:37




how would you call the function? Lets say you make it return different types, then also the caller has to be able to handle different types. Whatever you do it will be either complicated or broken or both. I agree that this is probably not the best design
– user463035818
Nov 19 at 12:37




2




2




See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
– palotasb
Nov 19 at 12:44




See this: arne-mertz.de/2018/05/modern-c-features-stdvariant-and-stdvisit
– palotasb
Nov 19 at 12:44




1




1




the problem is that you can't compare strings at compile time
– Stack Danny
Nov 19 at 12:59




the problem is that you can't compare strings at compile time
– Stack Danny
Nov 19 at 12:59












4 Answers
4






active

oldest

votes

















up vote
8
down vote



accepted










You can use a mix of template function and if constexpr (C++17):



template<typename T>
T valueOf() const {
if constexpr(std::is_same<T, bool>) return _boolValueOf();
else if constexpr(std::is_same<T, int>) return _intValueOf();
else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
}


Requires passing the type, but then the signature could be:



template<typename T>
T valueOf(const T& d) const {
if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
else if constexpr(std::is_same<T, int>) return _intValueOf(d);
else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
}





share|improve this answer



















  • 4




    Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
    – LogicStuff
    Nov 19 at 12:42








  • 1




    Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
    – Matthieu Brucher
    Nov 19 at 12:44






  • 1




    does Is_same(T, bool) also works? I thought is_same<T, bool>...
    – Zeta
    Nov 19 at 12:50






  • 1




    @Zeta Oops, that's a typo, of course <>!
    – Matthieu Brucher
    Nov 19 at 12:52






  • 1




    You need then to have a SFINAE fucntion for each type with enable_if :/
    – Matthieu Brucher
    Nov 19 at 13:01


















up vote
2
down vote













High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
If you want neither, there is no more left to try. Do you finally want to do it in C++?



If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.






share|improve this answer





















  • Why optional? That's not at all helpful in this scenario.
    – Nicol Bolas
    Nov 19 at 15:35










  • In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
    – Red.Wave
    Nov 19 at 16:21


















up vote
1
down vote













First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.



Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.



Not an ideal design.






share|improve this answer




























    up vote
    0
    down vote













    For you valueOf function, imo, user-defined conversion is also a choice:



    operator std::string()
    {
    return primitive_value._char_pointer;
    }
    operator bool()
    {
    return primitive_value._bool;
    }
    operator int()
    {
    return primitive_value._int;
    }
    ......


    Then you can use like this:



    var v1("hello");
    var v2(true);
    var v3(10);
    std::string a = v1;
    bool b = v2;
    int c = v3;

    std::cerr << static_cast<std::string>(v1) << 'n';
    std::cerr << std::boolalpha << static_cast<bool>(v2) << 'n';
    std::cerr << static_cast<int>(v3) << 'n';


    If you still hope to use function, just add a operator():



    var
    operator()()
    {
    return *this;
    }


    Then you can:



    var v1("hello");
    var v2(true);
    var v3(10);
    std::string a = v1();
    bool b = v2();
    int c = v3();


    But still a little ugly, right? Just add your valueOf function:



    var
    valueOf()
    {
    return *this;
    }


    Then:



    var v1("hello");
    var v2(true);
    var v3(10);
    std::string a = v1.valueOf();
    bool b = v2.valueOf();
    int c = v3.valueOf();


    But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
    But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.



    Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template






    share|improve this answer























      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',
      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%2f53374738%2fmultiple-return-type-from-function-c%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      8
      down vote



      accepted










      You can use a mix of template function and if constexpr (C++17):



      template<typename T>
      T valueOf() const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf();
      else if constexpr(std::is_same<T, int>) return _intValueOf();
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
      }


      Requires passing the type, but then the signature could be:



      template<typename T>
      T valueOf(const T& d) const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
      else if constexpr(std::is_same<T, int>) return _intValueOf(d);
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
      }





      share|improve this answer



















      • 4




        Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
        – LogicStuff
        Nov 19 at 12:42








      • 1




        Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
        – Matthieu Brucher
        Nov 19 at 12:44






      • 1




        does Is_same(T, bool) also works? I thought is_same<T, bool>...
        – Zeta
        Nov 19 at 12:50






      • 1




        @Zeta Oops, that's a typo, of course <>!
        – Matthieu Brucher
        Nov 19 at 12:52






      • 1




        You need then to have a SFINAE fucntion for each type with enable_if :/
        – Matthieu Brucher
        Nov 19 at 13:01















      up vote
      8
      down vote



      accepted










      You can use a mix of template function and if constexpr (C++17):



      template<typename T>
      T valueOf() const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf();
      else if constexpr(std::is_same<T, int>) return _intValueOf();
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
      }


      Requires passing the type, but then the signature could be:



      template<typename T>
      T valueOf(const T& d) const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
      else if constexpr(std::is_same<T, int>) return _intValueOf(d);
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
      }





      share|improve this answer



















      • 4




        Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
        – LogicStuff
        Nov 19 at 12:42








      • 1




        Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
        – Matthieu Brucher
        Nov 19 at 12:44






      • 1




        does Is_same(T, bool) also works? I thought is_same<T, bool>...
        – Zeta
        Nov 19 at 12:50






      • 1




        @Zeta Oops, that's a typo, of course <>!
        – Matthieu Brucher
        Nov 19 at 12:52






      • 1




        You need then to have a SFINAE fucntion for each type with enable_if :/
        – Matthieu Brucher
        Nov 19 at 13:01













      up vote
      8
      down vote



      accepted







      up vote
      8
      down vote



      accepted






      You can use a mix of template function and if constexpr (C++17):



      template<typename T>
      T valueOf() const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf();
      else if constexpr(std::is_same<T, int>) return _intValueOf();
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
      }


      Requires passing the type, but then the signature could be:



      template<typename T>
      T valueOf(const T& d) const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
      else if constexpr(std::is_same<T, int>) return _intValueOf(d);
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
      }





      share|improve this answer














      You can use a mix of template function and if constexpr (C++17):



      template<typename T>
      T valueOf() const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf();
      else if constexpr(std::is_same<T, int>) return _intValueOf();
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf();
      }


      Requires passing the type, but then the signature could be:



      template<typename T>
      T valueOf(const T& d) const {
      if constexpr(std::is_same<T, bool>) return _boolValueOf(d);
      else if constexpr(std::is_same<T, int>) return _intValueOf(d);
      else if constexpr(std::is_same<T, std::string>) return _std_stringValueOf(d);
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 19 at 13:37









      Lapys

      396313




      396313










      answered Nov 19 at 12:36









      Matthieu Brucher

      7,48011431




      7,48011431








      • 4




        Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
        – LogicStuff
        Nov 19 at 12:42








      • 1




        Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
        – Matthieu Brucher
        Nov 19 at 12:44






      • 1




        does Is_same(T, bool) also works? I thought is_same<T, bool>...
        – Zeta
        Nov 19 at 12:50






      • 1




        @Zeta Oops, that's a typo, of course <>!
        – Matthieu Brucher
        Nov 19 at 12:52






      • 1




        You need then to have a SFINAE fucntion for each type with enable_if :/
        – Matthieu Brucher
        Nov 19 at 13:01














      • 4




        Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
        – LogicStuff
        Nov 19 at 12:42








      • 1




        Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
        – Matthieu Brucher
        Nov 19 at 12:44






      • 1




        does Is_same(T, bool) also works? I thought is_same<T, bool>...
        – Zeta
        Nov 19 at 12:50






      • 1




        @Zeta Oops, that's a typo, of course <>!
        – Matthieu Brucher
        Nov 19 at 12:52






      • 1




        You need then to have a SFINAE fucntion for each type with enable_if :/
        – Matthieu Brucher
        Nov 19 at 13:01








      4




      4




      Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
      – LogicStuff
      Nov 19 at 12:42






      Under the convenient assumption that the requested type is known at compile-time. In that case, there should not be differently named functions doing conceptually the same thing in the first place. There should be overloads for the supported types.
      – LogicStuff
      Nov 19 at 12:42






      1




      1




      Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
      – Matthieu Brucher
      Nov 19 at 12:44




      Yes, under this assumption, which makes sense because at some point you need to write something at compile time.
      – Matthieu Brucher
      Nov 19 at 12:44




      1




      1




      does Is_same(T, bool) also works? I thought is_same<T, bool>...
      – Zeta
      Nov 19 at 12:50




      does Is_same(T, bool) also works? I thought is_same<T, bool>...
      – Zeta
      Nov 19 at 12:50




      1




      1




      @Zeta Oops, that's a typo, of course <>!
      – Matthieu Brucher
      Nov 19 at 12:52




      @Zeta Oops, that's a typo, of course <>!
      – Matthieu Brucher
      Nov 19 at 12:52




      1




      1




      You need then to have a SFINAE fucntion for each type with enable_if :/
      – Matthieu Brucher
      Nov 19 at 13:01




      You need then to have a SFINAE fucntion for each type with enable_if :/
      – Matthieu Brucher
      Nov 19 at 13:01












      up vote
      2
      down vote













      High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
      If you want neither, there is no more left to try. Do you finally want to do it in C++?



      If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.






      share|improve this answer





















      • Why optional? That's not at all helpful in this scenario.
        – Nicol Bolas
        Nov 19 at 15:35










      • In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
        – Red.Wave
        Nov 19 at 16:21















      up vote
      2
      down vote













      High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
      If you want neither, there is no more left to try. Do you finally want to do it in C++?



      If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.






      share|improve this answer





















      • Why optional? That's not at all helpful in this scenario.
        – Nicol Bolas
        Nov 19 at 15:35










      • In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
        – Red.Wave
        Nov 19 at 16:21













      up vote
      2
      down vote










      up vote
      2
      down vote









      High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
      If you want neither, there is no more left to try. Do you finally want to do it in C++?



      If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.






      share|improve this answer












      High-level and recomended solution is std::any, std::variant, std::optional. Low-level, hackish dangerous, final solution is union, void*, static_cast...
      If you want neither, there is no more left to try. Do you finally want to do it in C++?



      If are interested in the implementation of those high-level facilities, you can check the source code on open source implementations. But you will eventually find that those implementations device the low level constructs pointed above.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Nov 19 at 14:21









      Red.Wave

      72337




      72337












      • Why optional? That's not at all helpful in this scenario.
        – Nicol Bolas
        Nov 19 at 15:35










      • In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
        – Red.Wave
        Nov 19 at 16:21


















      • Why optional? That's not at all helpful in this scenario.
        – Nicol Bolas
        Nov 19 at 15:35










      • In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
        – Red.Wave
        Nov 19 at 16:21
















      Why optional? That's not at all helpful in this scenario.
      – Nicol Bolas
      Nov 19 at 15:35




      Why optional? That's not at all helpful in this scenario.
      – Nicol Bolas
      Nov 19 at 15:35












      In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
      – Red.Wave
      Nov 19 at 16:21




      In my interpretation, It has two return types: error or value. I have a nasty habit of generalization. Though not technically the case, I practically consider variant as a superset of optional and a subset of any.
      – Red.Wave
      Nov 19 at 16:21










      up vote
      1
      down vote













      First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.



      Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.



      Not an ideal design.






      share|improve this answer

























        up vote
        1
        down vote













        First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.



        Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.



        Not an ideal design.






        share|improve this answer























          up vote
          1
          down vote










          up vote
          1
          down vote









          First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.



          Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.



          Not an ideal design.






          share|improve this answer












          First to have different return types you need to use a template to differentiate the functions. Then you can call var(true).valueOf<bool>() for example. You will have to specify the template on every call so the compiler knows what function (and return type) to use. This can't be deduced on it's own.



          Secondly the var.type is a string that can only be checked at runtime. So var(42).valueOf<bool>() compiles just fine. You would have to check var.type against the template argument at runtime and throw an exception when the types don't match.



          Not an ideal design.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 19 at 14:43









          Goswin von Brederlow

          2,527724




          2,527724






















              up vote
              0
              down vote













              For you valueOf function, imo, user-defined conversion is also a choice:



              operator std::string()
              {
              return primitive_value._char_pointer;
              }
              operator bool()
              {
              return primitive_value._bool;
              }
              operator int()
              {
              return primitive_value._int;
              }
              ......


              Then you can use like this:



              var v1("hello");
              var v2(true);
              var v3(10);
              std::string a = v1;
              bool b = v2;
              int c = v3;

              std::cerr << static_cast<std::string>(v1) << 'n';
              std::cerr << std::boolalpha << static_cast<bool>(v2) << 'n';
              std::cerr << static_cast<int>(v3) << 'n';


              If you still hope to use function, just add a operator():



              var
              operator()()
              {
              return *this;
              }


              Then you can:



              var v1("hello");
              var v2(true);
              var v3(10);
              std::string a = v1();
              bool b = v2();
              int c = v3();


              But still a little ugly, right? Just add your valueOf function:



              var
              valueOf()
              {
              return *this;
              }


              Then:



              var v1("hello");
              var v2(true);
              var v3(10);
              std::string a = v1.valueOf();
              bool b = v2.valueOf();
              int c = v3.valueOf();


              But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
              But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.



              Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template






              share|improve this answer



























                up vote
                0
                down vote













                For you valueOf function, imo, user-defined conversion is also a choice:



                operator std::string()
                {
                return primitive_value._char_pointer;
                }
                operator bool()
                {
                return primitive_value._bool;
                }
                operator int()
                {
                return primitive_value._int;
                }
                ......


                Then you can use like this:



                var v1("hello");
                var v2(true);
                var v3(10);
                std::string a = v1;
                bool b = v2;
                int c = v3;

                std::cerr << static_cast<std::string>(v1) << 'n';
                std::cerr << std::boolalpha << static_cast<bool>(v2) << 'n';
                std::cerr << static_cast<int>(v3) << 'n';


                If you still hope to use function, just add a operator():



                var
                operator()()
                {
                return *this;
                }


                Then you can:



                var v1("hello");
                var v2(true);
                var v3(10);
                std::string a = v1();
                bool b = v2();
                int c = v3();


                But still a little ugly, right? Just add your valueOf function:



                var
                valueOf()
                {
                return *this;
                }


                Then:



                var v1("hello");
                var v2(true);
                var v3(10);
                std::string a = v1.valueOf();
                bool b = v2.valueOf();
                int c = v3.valueOf();


                But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
                But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.



                Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template






                share|improve this answer

























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  For you valueOf function, imo, user-defined conversion is also a choice:



                  operator std::string()
                  {
                  return primitive_value._char_pointer;
                  }
                  operator bool()
                  {
                  return primitive_value._bool;
                  }
                  operator int()
                  {
                  return primitive_value._int;
                  }
                  ......


                  Then you can use like this:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1;
                  bool b = v2;
                  int c = v3;

                  std::cerr << static_cast<std::string>(v1) << 'n';
                  std::cerr << std::boolalpha << static_cast<bool>(v2) << 'n';
                  std::cerr << static_cast<int>(v3) << 'n';


                  If you still hope to use function, just add a operator():



                  var
                  operator()()
                  {
                  return *this;
                  }


                  Then you can:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1();
                  bool b = v2();
                  int c = v3();


                  But still a little ugly, right? Just add your valueOf function:



                  var
                  valueOf()
                  {
                  return *this;
                  }


                  Then:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1.valueOf();
                  bool b = v2.valueOf();
                  int c = v3.valueOf();


                  But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
                  But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.



                  Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template






                  share|improve this answer














                  For you valueOf function, imo, user-defined conversion is also a choice:



                  operator std::string()
                  {
                  return primitive_value._char_pointer;
                  }
                  operator bool()
                  {
                  return primitive_value._bool;
                  }
                  operator int()
                  {
                  return primitive_value._int;
                  }
                  ......


                  Then you can use like this:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1;
                  bool b = v2;
                  int c = v3;

                  std::cerr << static_cast<std::string>(v1) << 'n';
                  std::cerr << std::boolalpha << static_cast<bool>(v2) << 'n';
                  std::cerr << static_cast<int>(v3) << 'n';


                  If you still hope to use function, just add a operator():



                  var
                  operator()()
                  {
                  return *this;
                  }


                  Then you can:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1();
                  bool b = v2();
                  int c = v3();


                  But still a little ugly, right? Just add your valueOf function:



                  var
                  valueOf()
                  {
                  return *this;
                  }


                  Then:



                  var v1("hello");
                  var v2(true);
                  var v3(10);
                  std::string a = v1.valueOf();
                  bool b = v2.valueOf();
                  int c = v3.valueOf();


                  But these solutions have many limitions. if constexpr provided by Matthieu Brucher is more powerful. Just all about provide a idea here : ).
                  But please note, unlike if constexpr, the ways I provided is not really multiple types return, just user-defined conversion.



                  Of course, there are more solutions, like sfinae(use enable_if and is_same in return type), or tag dispatch, but both of them require template







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 19 at 14:11

























                  answered Nov 19 at 13:58









                  陳 力

                  1,3241622




                  1,3241622






























                       

                      draft saved


                      draft discarded



















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53374738%2fmultiple-return-type-from-function-c%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

                      Wiesbaden

                      Marschland

                      Dieringhausen