I want to have function overloading, with the functions accepting boost::any lvalue and boost::any rvalue as arguments and exhibiting different behaviour based on that. A minimum reproducible example;
#include <boost/any.hpp>
#include <iostream>
#include <string>
#include <memory>
class MyClass {
public:
MyClass() {
a_int = -1;
b_string = "abc";
}
private:
int a_int;
std::string b_string;
public:
static void DumpMyClass(boost::any&& my_class_obj) {
std::cout << "rvalue reference" << std::endl;
}
static void DumpMyClass(const boost::any& my_class_obj) {
std::cout << "lvalue reference" << std::endl;
}
};
int main() {
std::shared_ptr<MyClass> c_sptr = std::make_shared<MyClass>();
MyClass::DumpMyClass(c_sptr);
MyClass::DumpMyClass(std::move(c_sptr));
return 0;
}
The output that I see is this;
$clang++ -std=c++11 any.cc -o code && ./code
rvalue reference
rvalue reference
I was hoping that the call MyClass::DumpMyClass(c_sptr); would have used the function which prints 'lvalue reference'. The behaviour is as per expectation if I change function signatures to have parameters of type std::shared_ptr<MyClass>&
and std::shared_ptr<MyClass>&&
instead of boost::any&
and boost::any&& respectively. By expectation, I mean that the output in that case is
lvalue reference
rvalue reference
The question here is why is it not able to distinguish between lvalue and rvalue reference of boost::any type, while it is able to do so for std::shared_ptr?
I went through this answer, which explains 'better matching' for overload resolution, but I'm not quite sure why it is not applying for boost::any, more so given that it is working for std::shared_ptr.
Versions: clang version 3.4.2, boost 1.53, also checked with boost 1.82.
The problem isn't with boost::any but the fact that there is an implicit conversion from std::shared_ptr to boost::any. We get the same effect when passing an integer into a function that accepts a double:
#include <print>
void f(double&& d) {
std::println("rvalue reference");
}
void f(const double& d) {
std::println("lvalue reference");
}
int main() {
double d = 1.0;
f(d); // lvalue reference
f(std::move(d)); // rvalue reference
int n = 1;
f(n); // rvalue reference
f(std::move(n)); // rvalue reference
}