In the code below, is there a way to implement const_foobar foobar_manager::get_foobar() const
in terms of the non-const version without the visit or equivalent code?
#include <variant>
#include <string>
struct foo {
int val;
std::string str;
};
struct bar {
double val;
std::string str;
};
using foobar = std::variant<foo, bar>;
using const_foobar = std::variant<const foo, const bar>;
class foobar_manager {
public:
foobar get_foobar() {
// the primary implementation of whatever needs to
// happen to get the variant we want would go here.
return foo{ 42, "mumble" };
}
const_foobar get_foobar() const {
// we want to get the const variant in terms of the
// the getting logic for the non-const case. Can
// it be done without a visit?
return std::visit(
[](auto v)->const_foobar {
return v;
},
const_cast<foobar_manager*>(this)->get_foobar()
);
}
};
int main() {
foobar_manager fm;
const auto& const_fm = fm;
auto test1 = fm.get_foobar();
auto test2 = const_fm.get_foobar();
return 0;
}
As already mentioned in the comments, you can use use the great C++23 feature "deducing this":
#include <variant>
#include <string>
#include <type_traits>
struct foo
{
int val;
std::string str;
};
struct bar
{
double val;
std::string str;
};
using foobar = std::variant<foo, bar>;
using const_foobar = std::variant<const foo, const bar>;
struct foobar_manager
{
auto get_foobar(this auto&& self)
{
if constexpr(std::is_const_v<decltype(self)>)
{
return const_foobar(foo(42, "mumble"));
}
else
{
return foobar(foo(42, "mumble"));
}
}
};
int main() {
foobar_manager fm;
const auto& const_fm = fm;
auto test1 = fm.get_foobar();
auto test2 = const_fm.get_foobar();
return 0;
}
Moreover, even with C++17 only (needed for std::variant), you can separate the complex logic to create the initial foo
in a separate (maybe static) function get_foo()
, and then simply call this function from the two implementations of get_foobar
struct foobar_manager
{
//...
static auto get_foo() { return foo(42, "mumble"); }
//...
auto get_foobar()
{
return foobar(get_foo());
}
auto get_foobar() const
{
return const_foobar(get_foo());
}
};