Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visitors can't return references, but they can with std::variant #39

Closed
ligfx opened this issue Apr 8, 2020 · 4 comments
Closed

Visitors can't return references, but they can with std::variant #39

ligfx opened this issue Apr 8, 2020 · 4 comments

Comments

@ligfx
Copy link

ligfx commented Apr 8, 2020

Example of the issue:

#define variant_CONFIG_SELECT_VARIANT 1
#include <variant>
#include "nonstd/variant.hpp"
#include <string>


struct tag_t {};

struct myvisitor {
  const std::string& operator()(const int&) const { throw std::exception(); }
  const std::string& operator()(const tag_t&) const { throw std::exception(); }
  const std::string& operator()(const std::string& s) const { return s; }
};

void test_std() {
   std::variant<int, tag_t, std::string> v("hello");
   std::visit(myvisitor(), v);
}

void test_nonstd() {
   nonstd::variant<int, tag_t, std::string> v("hello");
   nonstd::visit(myvisitor(), v);
}

int main() {
   test_std();
   test_nonstd();
}

The STL version of variant compiles and works. nonstd::variant throws a compile error:

./nonstd/variant.hpp:1925:16: error: reference to type 'const std::__1::basic_string<char>' requires an initializer
        return R();
@martinmoene
Copy link
Owner

martinmoene commented Apr 10, 2020

Hi @ligfx , Thanks for your message.

Example on Godbolt.

I think a relevant remark related to C++11 and later is No perfect forwarding here in order to simplify code.


Used wrong selection of nonstd::variant:

Trying on Godbolt, using clang 7.0.0, -std=c++17 (the first that successfully compiles std::visit(myvisitor(), v);) also successfully compiles for nonstd::variant.

So it seems more specific information is needed to assess what it is you run into, like compiler version and compilation flags.

@ligfx
Copy link
Author

ligfx commented Apr 10, 2020

Hi @martinmoene, I don't think perfect forwarding is related to this. There are two places in the code that explicitly try to default construct the return type, regardless of which version of C++:

and
default: return R();

When the return type is a const reference, it can't be default constructed.

Since a visitor is required to match all possible alternatives, that code should never be called, but the compiler doesn't like it anyways. What do you think about changing those lines to abort() or std::terminate? Something that the compiler knows won't return.

@martinmoene
Copy link
Owner

martinmoene commented Apr 10, 2020

Thanks @ligfx , will look into this later.

@ligfx
Copy link
Author

ligfx commented Apr 11, 2020

Great, thanks!

@ligfx ligfx closed this as completed Apr 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants