Reputation: 61
#include <iostream>
#include <vector>
namespace Cactus
{
namespace Json
{
class Value
{
public:
Value(){}
};
}
typedef std::vector< int > vectorInt;
inline Cactus::Json::Value& operator << (Cactus::Json::Value& os, const vectorInt& v)
{
return os;
}
inline Cactus::Json::Value& operator >> (Cactus::Json::Value& is, vectorInt& v)
{
return is;
}
}
namespace App
//namespace Cactus
{
void f()
{
Cactus::vectorInt ints;
Cactus::Json::Value val;
val << ints;
}
}
int main()
{
App::f();
}
meets error,
main.cpp: In function 'void App::f()':
main.cpp:38:13: error: no match for 'operator<<' (operand types are 'Cactus::Json::Value' and 'Cactus::vectorInt' {aka 'std::vector<int>'})
38 | val << ints;
| ~~~ ^~ ~~~~
| | |
| | Cactus::vectorInt {aka std::vector<int>}
| Cactus::Json::Value
But if use "namespace Cactus", it will compile. But I have to use "namespace App", any suggestions?
Updated: Problem is solved. Move the two operators to global namespace works. Or add using Cactus works too.
Upvotes: 0
Views: 102
Reputation: 1180
Those operator overloads must be in the scope where your f
function is. When you function f
is in Cactus
namespace, those operator overloads are in scope. But when it is under namespace App
, those go out of scope. So either put those operator overloads in global namespace, or put operator overloads in same namespace as class Value
, or put all functions using that operator in same namespace. Another way is to use using
statements inside functions using them to import them to global scope for that function.
Upvotes: 0
Reputation: 7369
It is known as ADL
. At least, in your example, function Cactus::Json::Value& operator << (Cactus::Json::Value& os, const vectorInt& v)
can't be found in the associated classes or namespaces of the type of the argument val
. Because the ADL
should be governed by the following rules:
For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered. The sets of namespaces and classes are determined entirely by the types of the function arguments (and the namespace of any template template argument). Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of namespaces and classes are determined in the following way:
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes. [...]
If an associated namespace is an inline namespace, its enclosing namespace is also included in the set. If an associated namespace directly contains inline namespaces, those inline namespaces are also included in the set.
So, the innermost enclosing namespace of class Value
is Json
. In the scope of Value
, there is no such an available function in it and similarly for namespace Json
, hence you meet that error.
How to resolve that?
Json
.namespace Json
to inline namespace Json
.Take one of them, then that will be fine.
Upvotes: 3