简体   繁体   中英

Code snippet doesnot compile under C++17, namespace issue?

#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.

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?

  1. Move all functions you provided to namespace Json .
  2. Modify namespace Json to inline namespace Json .

Take one of them, then that will be fine.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM