I have something like this in one method
autoPtr<LESModel> LESModel::New
95 (
96 const volVectorField& U,
97 const surfaceScalarField& phi,
98 transportModel& transport,
99 const word& turbulenceModelName
100 )
101 {
...
122 dictionaryConstructorTable::iterator cstrIter =
123 dictionaryConstructorTablePtr_->find(modelType);
...
143 return autoPtr<LESModel>
144 (
145 cstrIter()(U, phi, transport, turbulenceModelName)
146 );
147 }
If I am right cstrIter is a variable of class dictionaryConstructorTable::iterator (could not find this class though) and beginning with line 143 the constructor autoPtr<LesModel> is called and the result returned. The parentheses after the constructor autoPtr<LESModel> therefore should be parameters and since cstrIter is a variable I am wondering what the two parentheses after the variable mean. Perhaps I am misreading something?
C++ supports 'operator overloading', meaning you can define types that support syntax like a + b. This works by defining functions with names such as operator+. When an overloadable operator is used with a user defined type C++ looks for functions with these special names and, if a suitable function is found, treats the operator as a function call to the function.
One of the operators that one can overload is the function call operator. A member function named operator() will be called when you use an object name as though it's a function:
struct S {
void operator() (void) {
std::cout << "Hello, World!\n";
}
};
int main() {
S s;
s(); // prints "Hello, World!\n"
}
It looks like dictionaryConstructorTable::iterator overloads the function call operator and returns some type that also overloads the function call operator (or just uses the built-in operator).
Replacing the use of the function call operator with normal member functions may make it clearer what's happening:
return autoPtr<LESModel>( cstrIter.foo().bar(U, phi, transport, turbulenceModelName));
This looks like OpenFOAM, which has its own hash table implementation.
If you look in src/OpenFoam/containers/HashTable/HashTable/HashTable.H, line 454 (at least in my copy), you'll find that iterator overloads operator() and operator* to return a reference to the iterator's currently referenced value.
To clarify a little, C++ allows you to overload many of the operators you use to provide domain-specific functionality. This allows for, say, vector.add(otherVector) to use the "obvious" syntactic sugar of vector + otherVector instead. The downside is that what is obvious is not always so obvious, as this question demonstrates.
This construction
cstrIter()(U, phi, transport, turbulenceModelName)
means that at first a temporary object of type cstrIter is created using the default constructor
cstrIter()
And after that the function call operator is used for this object
cstrIter()(U, phi, transport, turbulenceModelName)
That it would be more clear you could rewrite the expression the following way
cstrIter obj;
obj(U, phi, transport, turbulenceModelName);
Related
To test and display the result of some functions of my library, I am creating a set of handy functions.
I have an execute function that looks like :
template <typename R, typename I>
std::string execute( const std::string& func_name, R(*func_ptr)( const I& ), const I& func_input );
It calls the function, and display the results and arguments in a formatted string that I can send to std::cout.
The problem is that some of my functions do not return convertible-to-string results. I thought I could simply overload the global ::operator std::string with something like:
template <typename T>
operator std::string( const std::vector<T>& v );
But GCC complains:
error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function
Well, the problem of course is that I cannot add member operators to std::vector, and even for my classes, I don't want to pollute them with "for testing" conversion operators.
I guess that I can add a layer of indirection and use a function instead of a conversion operator, but that would not be the more aesthetic solution. I could also overload ::operator << for std::ostream and use a std::ostringstream, but that also is not the cleanest solution.
I wondered if the global conversion operator is really not overloadable, and if so, why.
Conversion operators (cast operators) must be a member of the convertible class that produces the converted type. As assignment operators, they must be member functions, as your compiler is telling you.
Depending on how much effort you want to put into the debug part of it, you could try to use metaprogramming to forward your execute method to different actual implementations, providing specific ones for containers that will print the contents.
Why don´t you want to provide operator<< for your types? I think that is actually the idiomatic solution. Unlike other languages that you use methods that convert to string to produce printable results, in C++ the idiomatic way is providing operator<< and then using stringstreams (or boost::lexical_cast or some similar solution) to convert to strings based on the operator<< implementation. There is a simple utility class here to create a string from elements that override operator<< if you want to use that for a start point.
I wondered if the global conversion operator is really not overloadable, and if so, why.
No, there is no such thing. Conversion functions must be a member of a class. If it weren't so, it would make overload resolution a particularly vexing problem for the compiler by introducing ambiguities.
There is no user defined global conversion operator. You must control either the target type (in which case a non explicit one parameter constructor is the conversion operator) or the source type (in which case you have to overload the member operator target()).
A conversion function must be a member function. The function may not specify a return type, and the parameter list must be empty. They should be used sparingly and there should be a clear conversion path from one type to another type. Otherwise they can lead to unexpected results and mysterious errors.
Unfortunately there is no such thing as a global casting operator. Surprisingly. But templates are your friend.
Sometimes you do not want to expose the casting to the interface put would want to keep this anonymous for a specific implementation only. I usually add a template as() method to the class which can also do type checks in the cast, etc. and lets you handle the way you want to implement the casting (e.g. dynamic, shared, ref, etc).
Something like this:
template< class EvtT >const EvtT& as() const throw( std::exception )
{
const EvtT* userData = static_cast<const EvtT*>( m_UserData );
ASSERT( userData, "Fatal error! No platform specific user data in input event!" );
return *userData;
}
m_UserData is an anonymous type which only the implementation knows. While this is strictly a non-typed cast (I do not use type cecks here) this could be replaced by a dynamic_cast and proper casting exceptions.
The implementation simply does this:
unsigned char GetRawKey( const InputEvent& ie )
{
const UserEvent& ue = ie.as<const UserEvent>();
...
If the following class, Foo, is defined. It is said it overloads the unary ampersand (&) operator:
class Foo {
public:
Foo* operator&() { return nullptr; }
};
I think in this case, (reglardless of the fact that you can get the address of such an object by means of std::addressof() and other idiomatic tricks) there is no way to access/choose the original unary ampersand operator that returns the address of the object called on, am I wrong?
By overloading however, I understand that there is a set of functions of which one will be selected at compile-time based on some criteria. But this thinking doesn't seem to match the scenario above.
Why is it then called overloading and not something else like redefining or replacing?
Consider the following code:
int x;
Foo y;
&x; // built-in functionality
&y; // y.operator&();
We have two variables of different types. We apply the same & operator to both of them. For x it uses the built-in address-of operator whereas for y it calls your user-defined function.
That's exactly what you're describing as overloading: There are multiple functions (well, one of them is the built-in functionality, not really a "function") and they're selected based on the type of the operand.
You can't redefine a function or operator in C++, you can add only new use to it, defining new set of arguments. That's why it called overloading instead of redefining.
When you overload operator as a member of class you
1) defined it with first argument supposed to be an instance of that class
2) gave it access to all members of that class.
There are still definitions of operator& with different arguments and you have a non-zero chance to create situation where use of operator would be ambigous.
I have a class, let's call it Wrapper, that wraps a given type, let's say MyClass.
In reality, Wrapper is a class template, but I think that's not relevant here.
Wrapper exposes the wrapped MyClass by means of a conversion operator (just for reading).
When I create an operator for MyClass as free function (in my example a unary minus operator), this works as expected, I can use the operator also on the Wrapper class.
If I, however, implement the operator as a member function, the compiler complains: error: no match for ‘operator-’.
I thought the free function and the member function are equivalent in this case, why aren't they?
Is there a way to change the Wrapper class that a member operator or MyClass works?
If there isn't, does this suggest that it is in general preferable to implement an operator as free function instead of as member function?
Here's some code to illustrate the problem.
struct MyClass {
// This doesn't work:
void operator-() const {}
};
// It works with this instead of the member operator:
//void operator-(const MyClass&) {}
struct Wrapper {
operator MyClass() const { return MyClass(); }
};
int main() {
-Wrapper();
}
Here's a live example: http://ideone.com/nY6JzR
Question I thought the free function and the member function are equivalent in this case, why aren't they?
Answer
In order for -Wrapper() to work correctly, the compiler has to perform a lookup for operator-. It looks for the name operator- in the default namespace, in the class Wrapper, and the namespace where Wrapper is defined. It doesn't look at other classes and namespaces for the name.
That explains the compiler error when the operator-() is moved to MyClass and why it succeeds when it is defined as a non-member function.
Question Is there a way to change the Wrapper class that a member operator or MyClass works?
Answer There are two ways to resolve this.
Make the operator functions for MyClass non-member functions.
Create operator functions in MyClass as well as Wrapper, with the implementations in Wrapper being simple pass through functions. The good thing about this is that then you don't have to care whether the operator functions in MyClass are member functions or non-member functions.
Question If there isn't, does this suggest that it is in general preferable to implement an operator as free function instead of as member function?
Answer This can be a policy decision based on the choice you make to the previous answer.
I thought the free function and the member function are equivalent in
this case, why aren't they?
Lets see what happens when a conversion operator is used.
Essentially, there is a global operator function, which has a parameter of type MyClass. Now, since Wrapper has a conversion operator, the call operator-( Wrapper() ) will be inspected by overload resolution to find the best match - and overload resolution finds that there is a global operator function with parameter MyClass const& (or similiar). Then it tries to convert the Wrapper prvalue to MyClass const& and sees that there is a user-defined conversion sequence: One that uses the conversion operator to convert the Wrapper-object to a MyClass object, which then can be used to (copy-)initialize the reference.
If the operator function is a member instead, there is a problem: A global function call of the form operator-( Wrapper() ) does obviously not yield any viable functions. But the one that assumes the operator function is a member doesn't yield anything either - because operator- is not a member of Wrapper, therefore Wrapper().operator-() doesn't work and doesn't yield any viable functions either.
Remember: A class with a conversion operator does not inherit the members of the target type. If you wanted that, you should have inherited MyClass.
For a unary operator # with an operand of a type whose cv-unqualified
version is T1 [...] three sets of candidate functions, designated
member candidates, non-member candidates and built-in candidates, are
constructed as follows:
If T1 is a complete class type, the set of member candidates is the
result of the qualified lookup of T1::operator# (13.3.1.1.1);
otherwise, the set of member candidates is empty.
The set of non-member candidates is the result of the unqualified lookup of
operator# in the context of the expression according to the usual
rules for name lookup in unqualified function calls (3.4.2) except
that all member functions are ignored. [...]
I've read the section 13.5 of the working draft N3797 and I've one question. Let complex be a class type which represents complex numbers. We can define the following operator function:
complex operator+(double d, complex c)
{
return *new complex(d+c.get_real(),c.get_imagine());
}
But how this operator function can be implements as a complex member function? Or must I to declare this operator function in every module which I've intend to use them?
There are two ways to define a binary operator overload, such as the binary + operator, between two types.
As a member function.
When you define it as member function, the LHS of the operator is an instance of the class. The RHS of the operator is the argument to the function. That's why when you define it as member function, it can only have one argument.
As a free function.
These functions must have two arguments. The first argument is the LHS of the operator and the second argument is the RHS of the operator.
Since double is not a class, you have to define operator+ overload between double as LHS and complex as RHS as a free function, with double const& or double as the first argument type and complex const& or complex as the second argument type.
What you're looking for is this:
inline complex operator +(double d, const complex& c)
{
return complex(d+c.get_real(), c.get_imagine());
}
This cannot be a member function if you want the operator to handle a left-side of the operator as a double. It must be a free function, possibly friended if access to anything besides the public interface of complex is needed.
If you want the right side of the add-op to be a double, a member function can be crafted:
complex operator +(double d) const
{
return complex(d+get_real(), get_imagine());
}
Note this is assuming this definition is within the body of the complex class definition. But in the interest of clarity I would recommend both be inline free functions.
Implicit Construction
Lined up with the usual suspects, what you're at-least-appearing to try to do is generally done with an implicit conversion constructor and a general free-function. By providing this:
complex(double d) : real(d), imagine()
{
}
in the class definition a double can implicitly construct a temporary complex where needed. This allows this:
inline complex operator +(const complex& lhs, const complex& rhs)
{
return complex(lhs.get_real() + rhs.get_real(),
lhs.get_imagine() + rhs.get_imagine());
}
to be used as a general solution to all sensible manifestations of what you appear to want.
In C++, operator overloading requires class types. You cannot overload the + operator for the basic type double.
Also, except in certain circumstances (short-lived programs or throwaway code), the pointer resulting from a call to the new operator should be captured, so that it can be later released with delete, preventing a situation known as a memory leak.
For it to be a member, the first parameter must be of the class type(though it is not explicitly specified). But you are sending a double as first argument. If you need this to work either make it friend function or just non-member function which can work only using public interface of the Complex class. And as others pointed out, you are leaking memory.
To test and display the result of some functions of my library, I am creating a set of handy functions.
I have an execute function that looks like :
template <typename R, typename I>
std::string execute( const std::string& func_name, R(*func_ptr)( const I& ), const I& func_input );
It calls the function, and display the results and arguments in a formatted string that I can send to std::cout.
The problem is that some of my functions do not return convertible-to-string results. I thought I could simply overload the global ::operator std::string with something like:
template <typename T>
operator std::string( const std::vector<T>& v );
But GCC complains:
error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function
Well, the problem of course is that I cannot add member operators to std::vector, and even for my classes, I don't want to pollute them with "for testing" conversion operators.
I guess that I can add a layer of indirection and use a function instead of a conversion operator, but that would not be the more aesthetic solution. I could also overload ::operator << for std::ostream and use a std::ostringstream, but that also is not the cleanest solution.
I wondered if the global conversion operator is really not overloadable, and if so, why.
Conversion operators (cast operators) must be a member of the convertible class that produces the converted type. As assignment operators, they must be member functions, as your compiler is telling you.
Depending on how much effort you want to put into the debug part of it, you could try to use metaprogramming to forward your execute method to different actual implementations, providing specific ones for containers that will print the contents.
Why don´t you want to provide operator<< for your types? I think that is actually the idiomatic solution. Unlike other languages that you use methods that convert to string to produce printable results, in C++ the idiomatic way is providing operator<< and then using stringstreams (or boost::lexical_cast or some similar solution) to convert to strings based on the operator<< implementation. There is a simple utility class here to create a string from elements that override operator<< if you want to use that for a start point.
I wondered if the global conversion operator is really not overloadable, and if so, why.
No, there is no such thing. Conversion functions must be a member of a class. If it weren't so, it would make overload resolution a particularly vexing problem for the compiler by introducing ambiguities.
There is no user defined global conversion operator. You must control either the target type (in which case a non explicit one parameter constructor is the conversion operator) or the source type (in which case you have to overload the member operator target()).
A conversion function must be a member function. The function may not specify a return type, and the parameter list must be empty. They should be used sparingly and there should be a clear conversion path from one type to another type. Otherwise they can lead to unexpected results and mysterious errors.
Unfortunately there is no such thing as a global casting operator. Surprisingly. But templates are your friend.
Sometimes you do not want to expose the casting to the interface put would want to keep this anonymous for a specific implementation only. I usually add a template as() method to the class which can also do type checks in the cast, etc. and lets you handle the way you want to implement the casting (e.g. dynamic, shared, ref, etc).
Something like this:
template< class EvtT >const EvtT& as() const throw( std::exception )
{
const EvtT* userData = static_cast<const EvtT*>( m_UserData );
ASSERT( userData, "Fatal error! No platform specific user data in input event!" );
return *userData;
}
m_UserData is an anonymous type which only the implementation knows. While this is strictly a non-typed cast (I do not use type cecks here) this could be replaced by a dynamic_cast and proper casting exceptions.
The implementation simply does this:
unsigned char GetRawKey( const InputEvent& ie )
{
const UserEvent& ue = ie.as<const UserEvent>();
...