I have two generic methods (edit: actually operators but the issue is the same for methods) that are identical, except from that one uses its formal parameter by reference and the other method uses its formal parameter by value.
struct shout_t {
template<typename T>
shout_t& operator<<(T &x) { cout << x; return *this; } // by reference
template<typename T>
shout_t& operator<<(T x) { cout << x; return *this; } // by value
};
The intention of the "by-reference" method is to allow "large" objects to be used without copying. The "by-value" method is aimed at literals.
Since the "by-value" method can handle both cases (objects per se and literals), this gives an error:
int main() { // Here "large object" ~ string, "literal" ~ int
shout_t shout;
shout << 42; // OK
shout << "FTL"; // ERROR: Overloaded operator '<<' is ambiguous
}
The behaviour I was looking for is try first if "by-reference" method applies, if not, apply "by-value" method.
How to resolve this? How to obtain the intended behaviour of two methods that are identical except from their "by-value" and "by-reference" signature?
There are two scenarios here, either you might want to change the object passed as a parameter, or you don't. In the latter case, pass as const
-qualified reference:
struct shout_t {
template<typename T>
shout_t& operator<<(const T &item) { cout << item; return *this; }
};
and otherwise, use a forwarding reference in conjuction with std::forward
:
struct shout_t {
template<typename T>
shout_t& operator<<(T&& item) { cout << std::forward<T>(item); return *this; }
};
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments