I am writing a C++ class which represents an arithmetic type (a c++ wrapper around mpfr), and I'd like to support some functions found in <cmath> (I'll take std::sqrt as an example).
So I have the following class:
namespace ns
{
class MyClass
{
/* ... */
public:
friend MyClass sqrt(const MyClass& mc);
};
}
And I can use it this way:
MyClass c;
/* ... */
MyClass d = ns::sqrt(c);
MyClass e = sqrt(c); // Apparently I don't have to specify ns::
But I cannot use it this way:
MyClass f = std::sqrt(c);
Compiler (g++ (Debian 4.7.2-5)) error is: "no matching function for call to sqrt(ns::MyClass&)".
This is normal, but it's a problem to me. I need this to be valid, because MyClass is supposed to be used into existing template functions (that I'm not supposed to modify). For example:
template <typename T>
void func(T a)
{
/* ... */
T c = std::sqrt(a);
/* ... */
}
int main()
{
func<float>(3);
func<MyClass>(MyClass(3));
/* ... */
}
The following piece of code actually resolve my problem:
namespace std
{
using ns::sqrt;
}
But adding things into the std namespace seems very unnatural to me. I am afraid to run into unexpected troubles later, doing this.
Is it safe ? If not, why ?
Is there a better alternative ?
Function overloading is absolutely critical for C++-style template code. If I have to use different function names for different types, I can't write generic code. That would eliminate a large and heavily used part of the C++ library, and much of C++'s functionality. It's usually present in member function names.
This feature is present in most of the Object Oriented Languages such as C++ and Java. But C doesn't support this feature not because of OOP, but rather because the compiler doesn't support it (except you can use _Generic).
Rules of Function Overloading in C++The functions must have the same name. The functions must have different types of parameters. The functions must have a different set of parameters. The functions must have a different sequence of parameters.
Function overloading is one of the important features of object-oriented programming. It allows users to have more than one function having the same name but different properties. Overloaded functions enable users to supply different semantics for a function, depending on the signature of functions.
Adding stuff to namespace std
is prohibited by the standard. The correct way to tackle this problem is normally seen with swap
(that is available in the std
namespace, but that can be specialized by user-defined types to work more efficiently): when a template function needs to use e.g. sqrt
, it will do
using std::sqrt;
a=sqrt(b);
This way, for "regular" types it will use std::sqrt
("taken in" by the using
statement), while for your type your overload will prevail due to Koenig lookup (which, incidentally, is the reason of the behavior you observed at // Apparently I don't have to specify ns::
).
It’s not safe, because it’s not legal (§17.6.4.2.1):
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace
std
or to a namespace within namespacestd
unless otherwise specified. A program may add a template specialization for any standard library template to namespacestd
only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.
So you may add specialisations for your own types. You may not add overloads (or indeed anything else).
Your current code is the correct way of doing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With