This question already has answers here:
How do I assign an alias to a function name in C++?
(8 answers)
Closed 2 years ago.
If I have a class Foo in namespace bar:
namespace bar
{
class Foo { ... }
};
I can then:
using Baz = bar::Foo;
and now it is just like I defined the class in my namespace with the name Baz.
Is it possible to do the same for functions?
namespace bar
{
void f();
}
And then:
using g = bar::f; // error: ‘f’ in namespace ‘bar’ does not name a type
What is the cleanest way to do this?
The solution should also hold for template functions.
Definition: If some entity B is an alias of A, than if any or all usages (not declarations or definitions of course) of A are replaced by B in the source code than the (stripped) generated code remains the same. For example typedef A B is an alias. #define B A is an alias (at least). T& B = A is not an alias, B can effectively implemented as an indirect pointer, wheres an "unaliased" A can use "immediate semantics".
You can define a function alias (with some work) using perfect forwarding:
template <typename... Args>
auto g(Args&&... args) -> decltype(f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
This solution does apply even if f is overloaded and/or a function template.
The constexpr function pointer can be used as a function alias.
namespace bar
{
int f();
}
constexpr auto g = bar::f;
It is highly likely (but not guaranteed by the language) that using g uses bar::f directly.
Specifically, this depends on compiler version and optimization level.
In particular, this is the case for:
GCC 4.7.1+, without optimization,
Clang 3.1+, without optimization,
MSVC 19.14+, with optimization.
See assembly generated by these compilers.
Classes are types, so they can be aliased with typedef and using (in C++11).
Functions are much more like objects, so there's no mechanism to alias them. At best you could use function pointers or function references:
void (*g)() = &bar::f;
void (&h)() = bar::f;
g();
h();
In the same vein, there's no mechanism for aliasing variables (short of through pointers or references).
It's possible to introduce the function into a different scope without changing its name. That means that you can alias a function with a different qualified name:
namespace bar {
void f();
}
namespace baz {
using bar::f;
}
void foo() {
baz::f();
}
Absolutely:
#include <iostream>
namespace Bar
{
void test()
{
std::cout << "Test\n";
}
template<typename T>
void test2(T const& a)
{
std::cout << "Test: " << a << std::endl;
}
}
void (&alias)() = Bar::test;
void (&a2)(int const&) = Bar::test2<int>;
int main()
{
Bar::test();
alias();
a2(3);
}
Try:
> g++ a.cpp
> ./a.out
Test
Test
Test: 3
>
A reference is an alias to an existing object.
I just created a reference to a function. The reference can be used in exactly the same way as the original object.
It's not standard C++, but most compilers provide a way of doing this. With GCC you can do this:
void f () __attribute__ ((weak, alias ("__f")));
This creates the symbol f as an alias for __f. With VC++ you do the same thing this way:
#pragma comment(linker, "/export:f=__f")
You can use good old macros
namespace bar
{
void f();
}
#define f bar::f
int main()
{
f();
}
Related
This question got me wondering whether it is ever useful/necessary to fully qualify class names (including the global scope operator) in an out-of-class member function definition.
On the one hand, I've never seen this done before (and the syntax to properly do so seems obscure). On the other, C++ name lookup is very non-trivial, so maybe a corner case exists.
Question:
Is there ever a case where introducing an out-of-class member function definition by
ReturnType (::Fully::Qualified::Class::Name::MemberFunctionName)(...) { ... }
would differ from
ReturnType Fully::Qualified::Class::Name::MemberFunctionName(...) { ... } (no global scope :: prefix)?
Note that member function definitions must be put into a namespace enclosing the class, so this is not a valid example.
A using-directive can cause Fully to be ambiguous without qualification.
namespace Foo {
struct X {
};
}
using namespace Foo;
struct X {
void c();
};
void X::c() { } // ambiguous
void ::X::c() { } // OK
It's necessary if one is a masochist and enjoys writing stuff like this
namespace foo {
namespace foo {
struct bar {
void baz();
};
}
struct bar {
void baz();
};
void foo::bar::baz() {
}
void (::foo::bar::baz)() {
}
}
One can of course write the second overload as foo::foo::bar::baz in global scope, but the question was whether or not the two declarations can have a different meaning. I wouldn't recommend writing such code.
If a using directive is used then there can be a confusing code.
Consider the following demonstrative program
#include <iostream>
#include <string>
namespace N1
{
struct A
{
void f() const;
};
}
using namespace N1;
void A::f() const { std::cout << "N1::f()\n"; }
struct A
{
void f() const;
};
void ::A::f() const { std::cout << "::f()\n"; }
int main()
{
N1::A().f();
::A().f();
return 0;
}
So for readability this qualified name
void ::A::f() const { std::cout << "::f()\n"; }
shows precisely where the function is declared.
why does this code work? with c++14
// Example program
#include <iostream>
#include <string>
using namespace std;
auto fun()
{
struct a
{
int num = 10;
a()
{
cout << "a made\n";
}
~a()
{
cout << "a destroyed\n";
}
};
static a a_obj;
return a_obj;
}
int main()
{
auto x = fun();
cout << x.num << endl;
}
how is the type a visible in main? if i change auto x= to a x= it obviously doesn't compile, but how does main know about the type a?
The static declaration is there since I was trying to test for something else but then I stumbled upon this behavior.
Running it here: https://wandbox.org/permlink/rEZipLVpcZt7zm4j
This is all surprising until you realize this: name visibility doesn't hide the type. It just hides the name of the type. Once you understand this it all makes sense.
I can show you this without auto, with just plain old templates:
auto fun()
{
struct Hidden { int a; };
return Hidden{24};
}
template <class T> auto fun2(T param)
{
cout << param.a << endl; // OK
}
auto test()
{
fun2(fun()); // OK
}
If you look closely you will see this is the same situation as yours:
you have a struct Hidden which is local to fun. Then you use an object of type Hidden inside test: you call fun which returns a Hidden obj and then you pass this object to the fun2 which in turn has no problem at all to use the object Hidden in all it's glory.
as #Barry suggested the same thing happens when you return an instance of a private type from a class. So we have this behavior since C++03. You can try it yourself.
C++14 is made to be more and more tolerant with auto. Your question is not clear, because you're not stating what the problem is.
Now let's tackle your question differently: Why does it not work with a x = ...?
The reason is that the struct definition is not in the scope of the main. Now this would work:
// Example program
#include <iostream>
#include <string>
using namespace std;
struct a
{
int num = 10;
};
auto fun()
{
static a a_obj;
return a_obj;
}
int main()
{
a x = fun();
cout << x.num << endl;
}
Now here it doesn't matter whether you use a or auto, because a is visible for main(). Now auto is a different story. The compiler asks: Do I have enough information to deduce (unambiguously) what the type of x is? And the answer is yes, becasue there's no alternative to a.
I have to define two functions, say, foo() and bar() in the same namespace and the same file. For the definition of the first, foo(), I want to use all symbols of, say, namespace other, but don't want symbols from namespace other to be automatically in scope for my other function, bar(). Is this possible? How?
(note: I don't want to know about alternative "solutions" either avoiding this problem of mitigating it, such as namespace o=other etc.)
Yes, it is possible:
void foo()
{
using namespace abc;
....
}
or
void foo()
{
using abc::x;
using abc::y;
using abc::z;
....
}
#include <iostream>
void quux() { std::cout << "root\n"; }
namespace other {
void quux(int x = 0) { std::cout << "other\n"; }
}
namespace taxes {
void foo() {
using namespace other;
quux(3);
};
void bar() {
quux();
}
}
int main() {
taxes::foo();
taxes::bar();
}
Live example
Note that quux in bar would be ambiguous if it could see other::quux, but it cannot.
On the other hand, this does not give you access to namespace other in the 'head' of the function foo (the parameters etc), but that is a rare requirement. There might be a solution involving inline namespaces or the like, but probably not worth the confusion.
I have a question regarding the standard ADL resolution in C++.
Here is a sample code explaining my enquiry:
#include <string>
// The mechanism:
namespace A {
template< class C >
::std::string scope(const C*)
{ return "A"; }
namespace B {
template< class C >
::std::string scope(const C *foo)
{ return A::scope(foo)+"::B"; }
} // namespace B
} // namespace A
::std::string scope(...)
{ return ""; }
// The test classes
struct foo {};
namespace A {
struct foo {};
namespace B {
struct foo {};
}
}
// The usage
int main()
{
foo *Foo=0;
A::foo *FooA=0;
A::B::foo *FooB=0;
scope(Foo); // OK, returns ""
scope(FooA); // OK, returns "A"
scope(FooB); // On one compiler, OK returns "A::B" ; On another, compiler error "Ambiguous call" between A::scope() and A::B::scope()
}
So, my question is what is the standard regarding ADL?
Should all the functions from parent namespaces of the argument be found, or only the functions available in the (nested) namespace of the argument + the global functions?
This program has been tested on MSVC 2008 (and compiles with SP but not without...)
According to the standard, ADL works (modulo a couple of special rules)
"as if" the function name were preceded by the namespace; in your last
line, lookup should precede as if you'd written A::B::scope. Which
does not look in the surrounding namespaces.
Note that even within namespace A::B, there would be no ambiguity; in
A::B, A::B::scope hides A::scope. Unqualified name lookup stops
in the scope where it first finds the name.
#include "stdafx.h"
#include <iostream>
using namespace std;
template<class Type>
struct X
{
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
};
}
void run_1()const
{//if this does
Type::alloc();
}
};
struct T
{
static void alloc()
{}
};
int _tmain(int argc, _TCHAR* argv[])
{
X<T> x;
x.run_1();
return 0;
}
AFAIC lambda is a unnamed fnc, so if that's true why run doesn't compile and run_1 does?
Using VS2010 sp beta1.
You'll have to pass it in to the lambda:
void run()const
{//Why on earth this doesn't work?
auto alloc = Type::alloc;
[&]()
{
alloc();
};
}
I have to admit I am not quite sure, but I think is only a VS 2010 limitation and it should compile fine in C++0x (cf. templates, typename, lambda -> dependent names not dependent?). I think the mechanics of what you see are like following:
When defining template, types defined by template parameters are not "fully fledged" typenames in some aspects. One example demonstrating this is that while someone might expect X<Foo>::Type (with X from your example) to return Foo, it does not.
You have to call the lambda. It is a functor so you need a () at the end of it to effectively call the lambda.
/* Code does NOT answer question above...
void run()const
{//Why on earth this doesn't work?
[&]()
{
Type::alloc();
}(); //very important parenthesis if you wish to call the lambda
}*/
I seem to have misread the question. Sorry.
But there is already a similar post on SO Template type is not "seen" by the compiler inside a lambda
And here is another link that refers to the same problem, with a quote from the standard about this.
templates, typename, lambda -> dependent names not dependent?