Calling a Function from a Namespace

How do I call a function in a different namespace?

Following code works with gcc (as expected). Your problem must be with something that is not in the question.

#include <iostream>

namespace example
{
void dummy() { std::cout << "Dummy\n"; }
}

namespace buzz
{
void test() { example::dummy(); }
}

int main()
{
buzz::test();
}

Calling functions within namespaces

This does, I believe, exactly what the OP wants, but it's horrible. Every CPP file that includes space.h is going to instantiate bar's 1 and 2 and init. Naming collision hell when the linker tries to sort it all out.

#ifndef SPACE_H
#define SPACE_H
#include <iostream>
namespace space
{
class bar
{
public:
// use your own stuff here. This is for sample use only.
bar(const std::string & str):mStr(str)
{

}
friend std::ostream &operator<<(std::ostream & out, const bar &bq)
{
out << bq.mStr;
return out;
}
private:
std::string mStr;
};
bar *bar1; // consider using std::unique_ptr in place of the raw pointer
bar *bar2;

class Init
{
public:
Init()
{
bar1 = new bar("bar, bar, bar");
bar2 = new bar("barbara anne");
}
virtual ~Init() // std::unique_ptr makes this destructor unnecessary
{
delete bar1;
delete bar2;
}
}
Init init; // init will construct and assign the bars before main
// and destruct and delete the bars when the program exits
}
#endif

static makes it marginally better static restricts each bar and init to each including CPP file, but now you have the variables duplicated in each including CPP file, more RAM use and changing one does not change the others.

    static bar *bar1;
static bar *bar2;

class Init
{
public:
Init()
{
bar1 = new bar("bar, bar, bar");
bar2 = new bar("barbara anne");
}
virtual ~Init()
{
delete bar1;
delete bar2;
}
};
static Init init;

Another tweak doesn't do exactly what OP wants, but it's close, a lot safer that take 1, and unified across compilation units unlike take 2. extern instructs the compiler to allow use of bars 1 and 2 without instantiating them, but that means someone has to actually allocate space for them.

    extern bar *bar1;
extern bar *bar2;

class Init
{
public:
Init()
{
bar1 = new bar("bar, bar, bar");
bar2 = new bar("barbara anne");
}
virtual ~Init()
{
delete bar1;
delete bar2;
}
};

And a main CPP to demonstrate use

#include <iostream>
#include "space.h"

// allocate the bars and the Init object
space::bar *space::bar1;
space::bar *space::bar2;

space::Init init;

int main()
{
std::cout << *space::bar1 << std::endl;
std::cout << *space::bar2 << std::endl;
return 0;
}

Calling function in a namespace without qualification

According to ISO C++14 standard, at §3.4.2:

When the postfix-expression in a function call is an unqualified-id, other namespaces not considered during the usual unqualified lookup may be searched, and in those namespaces, namespace-scope friend function or function template declarations not otherwise visible may be found. These modifications to the search depend on the types of the arguments (and for template template arguments, the namespace of the template argument).

And following:

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 is determined entirely by the types of the function arguments..

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.

Actually you can even prevent this from happening by enclosing the function name:

(bar)(a); // doens't compile

while

(B::bar)(a); // does compile

Mind also that this applies only to the innermost namespace, which means that in the following situation you need to qualify the namespace:

namespace B {
namespace C {
struct A {};
}

void bar(const C::A& a) { ... }
}

How to call function A from function B within the same namespace?

I recommend placing the "namespace" inside a function scope. Everything not explicitly public will be naturally private:

var Namespace = (function() {
var self = {};

// Private
var A = function() {
...
};

// Public
self.B = function() {
A();
}

return self;
}());

Namespace.B(); // Works
Namespace.A(); // Doesn't work

Calling a function from another namespace from a string C#

Based on "Sticky bit" answer:

Type thisType = Type.GetType("System.Console");
MethodInfo theMethod = thisType.GetMethod("WriteLine");

theMethod.Invoke(null, new object[1] { "Hello" });

But you have to be careful about method overloads, because then you can get

System.Reflection.AmbiguousMatchException

Also, this aproach isnt the best, and it's a sign of a design problem.
Another thing to take in mind, is using "nameof" operator to tell namespaces names and methods, that's to avoid magic strings.
Applying this on the example i gave:

Type thisType = Type.GetType(nameof(System) + "." + nameof(Console));
MethodInfo theMethod = thisType.GetMethod(nameof(Console.WriteLine));

theMethod.Invoke(null, new object[1] { "Hello" });

Then the caller:

CallMethodFromName(nameof(Console) + "." + nameof(Console.WriteLine), "Hello, world!");

Use a function in different file and different namespace in Visual C++

The problem that compiler does not know about namespace MYSpace when compiling Source.cpp.

#include <iostream>

using namespace std;

namespace MyNameSpace
{
int PrintHello();
extern int tempCount;
}
int main()
{
int i;
MyNameSpace::PrintHello();
cout << MyNameSpace::tempCount << endl;
cout << "Hello from main" << endl;
}

But this sample is useless. It work only because you have only one consumer .cpp.

You should use .h file and then include it (PrintFunc.h) in Source.cpp and any other .cpp when you want to use that funtions.

I'll write an example:

Print.h

#pragma once

namespace MyNameSpace
{
int PrintHello();
extern int tempCount;
}

Notice that we dont't use additional includes and using namespace here. We would use includes only to use some classes in functions interfaces.
using namespace could "spoil" consumer's .cpp or .h.

Print.cpp

#include <iostream>
#include "Print.h"

using namespace std;

int MyNameSpace::tempCount = 111;

int MyNameSpace::PrintHello()
{
cout << "Hello from Source1" << endl;
return 0;
}

Here we can set any include it will not touch any other files.

And consumer .cpp:

#include <iostream>
#include "Print.h"

using namespace std;

int main()
{
int i;
MyNameSpace::PrintHello();
cout << MyNameSpace::tempCount << endl;
cout << "Hello from main" << endl;
}

VS specific: #pragma once and for VS you have to #include "stdafx.h" at first line in any .cpp

calling a function from a class inside a namespace?

I was able to get this working using the following methods.

  1. Create a new folder in VSCode. I named it SO_66629443_20210315 and put it in my X:\test folder

  2. Add the 3 files.

  3. Fix the missing includes. legeplads.cpp requires #include <iostream> and #include "frileg.h" and main.cpp requires #include "frileg.h"

  4. Modify main.cpp to use the frileg namespace when constructing a; use frileg::legeplads a; instead of legeplads a;

So at this point the files look like:

main.cpp

#include "frileg.h"

int main()
{

frileg::legeplads a;
a.x = 1;
a.y = 2;
a.z = 3;
a.print();
return 0;
}

legeplads.cpp

#include "frileg.h"
#include <iostream>

void frileg::legeplads::print()
{
std::cout << "pos: {" << x << ", " << y << ", " << z << "}" << std::endl;
}

frileg.h

namespace frileg
{
class legeplads
{
public:
int x;
int y;
int z;
void print();
};
}

  1. Modify tasks.json to compile more than 1 file as the documentation tells you here: https://code.visualstudio.com/docs/cpp/config-mingw#_modifying-tasksjson

so the tasks.json file looks exactly like:

{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "C:\\msys64\\mingw64\\bin\\g++.exe",
"args": [
"-g",
"${workspaceFolder}\\*.cpp",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "C:\\msys64\\mingw64\\bin"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

Note that I am using msys2 for my mingw installation. I installed that using these instructions: https://www.msys2.org/

And finally executing the program in VSCode looked like this:

PS X:\test\SO_66629443_20210315>  & 'c:\Users\dresc\.vscode\extensions\ms-vscode.cpptools-1.2.2\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-gtfgey3y.olb' '--stdout=Microsoft-MIEngine-Out-l2sggqju.oz3' '--stderr=Microsoft-MIEngine-Error-zgahgwi3.zwy' '--pid=Microsoft-MIEngine-Pid-0mc3zqbv.bqm' '--dbgExe=C:\msys64\mingw64\bin\gdb.exe' '--interpreter=mi'    
pos: {1, 2, 3}

Using functions from global namespace in a namespace

Is it a good practice, or there is a more elegant solution?

IMHO, you can use it with third party library. It is clear and expressive enough. It would be better if you could write:

void World() {
::f(100); // f from global namespace
::f(100, 200); // f from global namespace
f(100, 200, 300); // f NOT from global namespace
}

because then it is clearly visible which function is and which is not from the global namespace but this solution does not work for you since you cannot modify implementation of World function.

Can I only import f(int) and not f(int, int)?

Yes. You can do the following in order to import only f(int) function:

void f(int) {}

namespace Hello {
using ::f; // only void f(int) is defined before this line
// therefore, it is the only overload being imported to the Hello namespace
}

void f(int,int) {}

Demo

UPDATE

If you want to import only one overload of an operator<<, not an ordinary function, then you could wrap each overload in a separate namespace like this:

namespace XX {

struct X {
int x;
};

std::ostream& operator<<(std::ostream& os, X const& x) {
return os;
}

}

namespace YY {

std::ostream& operator<<(std::ostream& os, Y const& y) {
return os;
}

struct Y {
double y;
};

}

namespace Hello {
using ::XX::X;
using ::XX::operator<<;
using ::YY::Y;
}

Check it out live.



Related Topics



Leave a reply



Submit