no error on lack of namespace qualifiers in C++ - c++

I'm working on a small C++ project and ran into some behavior regarding namespaces that looks really weird to me. I've defined all my classes and functions in a namespace my_project:
// point.hpp:
namespace my_project {
template <size_t dim> class Point { /* snip */ };
}
// convex_hull.hpp:
namespace my_project {
std::vector<size_t> convex_hull(const std::vector<Point<2> >& xs);
}
I then went to write a test for everything:
// convex_hull_test.cpp:
#include <my_project/convex_hull.hpp>
using my_project::Point;
int main()
{
Point<2> p1 = /* snip */;
std::vector<Point<2> > xs = {p1, p2, p3, p4, p5, p6};
std::vector<size_t> hull = convex_hull(xs);
/* snip */
return 0;
}
Everything worked just fine, but the next day I looked at it again and realized that I should have written this line instead:
std::vector<size_t> hull = my_project::convex_hull(xs);
because I never had using my_project::convex_hull anywhere. And yet I don't get any errors for using an undefined symbol when I compile this. Why can I use this function without a namespace prefix?
This is true for several other functions that I've defined. When I leave off the line using my_project::Point; I do get errors for using Point without namespace qualification. Are there different rules for functions, classes or templates about namespace qualification? Are the rules the same, indicating that there's something else weird going on?
I tried this with clang, g++ and icc, on more than one machine. I tried to construct a minimal test case, but the compiler threw the error that I thought it should in this case.

the type of xs must have been available in the namespace my_project. What is happening is called Argument-dependent lookup.
The C++ standard permits it. If you want to prevent ADL, try
std::vector<size_t> hull = (convex_hull)(xs);
Putting parentheses prevents argument-dependent lookup, try that, the compiler should complain.
EDIT: based on OP's edit
See Alan Stokes comment on this answer.

Related

Getting "instantiation resulted in unexecpted type" with MSVC

In a library of mine, I have the following bit of code (snipped for brevity):
namespace memory {
namespace managed {
namespace detail {
template <typename T>
inline T get_scalar_range_attribute(
region_t region,
cudaMemRangeAttribute attribute)
{ /* snip */ }
} // namespace detail
struct region_t : public memory::region_t {
// snip
bool is_read_mostly() const
{
return detail::get_scalar_range_attribute<bool>(
*this, cudaMemRangeAttributeReadMostly);
}
// snip
}
} // namespace managed
} // namespace memory
Now, with GCC and Clang on Linux, this works fine. But with MSVC 16.8.4 on Windows, a user of mine gets:
error : template instantiation resulted in unexpected function type of "__nv_bool
(cuda::memory::managed::region_t, cudaMemRangeAttribute)" (the meaning of a name
may have changed since the template declaration -- the type of the template is "T
(cuda::memory::region_t, cudaMemRangeAttribute)"
I don't understand how an instantiation can result in something unexpected, ever. I also don't see how my "name hiding" of one class name with another should have any effect on the template instantiation.
(Credit goes to #Guillaume Racicot for most of this.)
The issue here is the timing of name lookup.
Other compiles, when encountering the template declaration, region_t, seem to look for previously-defined region_t's; find memory::region_t; and be ok with that. (Correct me if I'm wrong).
MSVC, however, performs the lookup twice: Once when encountering the declaration+definition, then again upon instantiation - with different contexts both times. So, the first time, it finds memory::region_t; and the second time it finds memory::managed::region_t. This is "unexpected"...
This behavior of MSVC is apparently due to its "permissive" compilation mode (which is enabled by default). This is a bit weird, seeing how it is less permissive in this case, but that's just how it is.

g++ std::visit leaking into global namespace?

I just bounced into something subtle in the vicinity of std::visit and std::function that baffles me. I'm not alone, but the only other folks I could find did the "workaround and move on" dance, and that's not enough for me:
https://github.com/fmtlib/fmt/issues/851
https://github.com/jamboree/bustache/issues/11
This may be related to an open issue in the LWG, but I think something more sinister is happening here:
https://cplusplus.github.io/LWG/issue3052
Minimal Example:
// workaround 1: don't include <variant>
#include <variant>
#include <functional>
struct Target
{
Target *next = nullptr;
};
struct Visitor
{
void operator()(const Target &tt) const { }
};
// workaround 2: concretely use 'const Visitor &' instead of 'std::function<...>'
void visit(const Target &target, const std::function<void(const Target &)> &visitor)
{
visitor(target);
if(target.next)
visit(*target.next,visitor); // workaround 3: explicitly invoke ::visit(...)
//^^^ problem: compiler is trying to resolve this as std::visit(...)
}
int main(int argc, char **argv, char **envp)
{
return 0;
}
Compile with g++ -std=c++17, tested using:
g++-7 (Ubuntu 7.5.0-3ubuntu1~18.04)
g++-8 (Ubuntu 8.4.0-1ubuntu1~18.04)
The net result is the compiler tries to use std::visit for the clearly-not-std invocation of visit(*target.next,visitor):
g++-8 -std=c++17 -o wtvariant wtvariant.cpp
In file included from sneakyvisitor.cpp:3:
/usr/include/c++/8/variant: In instantiation of ‘constexpr decltype(auto) std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = Target&; _Variants = {const std::function<void(const Target&)>&}]’:
wtvariant.cpp:20:31: required from here
/usr/include/c++/8/variant:1385:23: error: ‘const class std::function<void(const Target&)>’ has no member named ‘valueless_by_exception’
if ((__variants.valueless_by_exception() || ...))
~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/8/variant:1390:17: error: no matching function for call to ‘get<0>(const std::function<void(const Target&)>&)’
std::get<0>(std::forward<_Variants>(__variants))...));
~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In my real use case, I thought someone had snuck a "using namespace std" into the header space of my tree and I was gonna be grumpy. However, this minimal example demonstrates otherwise.
Critical Question: given that I have not created nor used any namespaces, why is std::visit(...) getting involved here at all?
WRT workaround 1: At least in the variant header, visit(...) is declared properly in the std namespace
WRT workaround 2: If the second argument is anything other than a std::function, it compiles just fine, leading me to believe that something more subtle is going on here.
WRT workaround 3: I understand that two colons are a small price to pay, but that they are necessary at all feels dangerous to me given my expectations for what it means to put a free function like visit(...) into a namespace.
Any one of the three marked workarounds will suppress the compiler error, but I'm personally intolerant of language glitches that I can't wrap my head around (Though I understand the necessity, I'm still uneasy about how often I have to sprinkle 'typename' into templates to make them compile).
Also of note, if try to make use of other elements of the std namespace without qualification (e.g., try a naked 'cout'), the compiler properly grumps about not being able to figure out the 'cout' that I'm after, so it's not as though the variant header is somehow flattening the std namespace.
Lastly, this problem persists even if I put my visit() method in its own namespace: the compiler really wants to use std::visit(...) unless I explicitly invoke my_namespace::visit(...).
What am I missing?
The argument visitor is an std::function, which is in the namespace std, so argument-dependent lookup finds visit in the namespace std as well.
If you always want the visit in the global namespace, say so with ::visit.

Difference between sibling namespaces in nested vs global context

I have some C++ libraries that are written using nested namespaces. These libraries use many mathematical functions that, for readability, are better off read without explicitly specifying namespaces. Right now, a simplified version of the code would look like this.
namespace Base::Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Base::Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
We wanted to move to use flatter namespaces mostly to make it easier to extend the library with sibling code. We had hoped that a simple change like this would work:
namespace Sibling1 {
float cos(float x) { return cosf(x); }
};
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
};
Instead this fails now since Sibling2::f() calls cos(x) that is now ambiguous.
I have two questions
why is it ambiguous now and not int the first version?
is it possible to obtain the behavior we had before without listing all functions explicitly using using Sibling1::cos?
The ambiguity is due to how using directives work.
[namespace.udir] (emphasis mine)
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using-directive
appears after the using-directive. During unqualified name lookup
([basic.lookup.unqual]), the names appear as if they were declared in
the nearest enclosing namespace which contains both the
using-directive and the nominated namespace. [ Note: In this context,
“contains” means “contains directly or indirectly”. — end note ]
3 A using-directive does not add any members to the declarative
region in which it appears. [ Example:
namespace A {
int i;
namespace B {
namespace C {
int i;
}
using namespace A::B::C;
void f1() {
i = 5; // OK, C​::​i visible in B and hides A​::​i
}
}
namespace D {
using namespace B;
using namespace C;
void f2() {
i = 5; // ambiguous, B​::​C​::​i or A​::​i?
}
}
void f3() {
i = 5; // uses A​::​i
}
}
void f4() {
i = 5; // error: neither i is visible
}
— end example ]
So given your structure of namespaces, according to bit I made bold in paragraph 2, when you write
using namespace Sibling1;
It kinda translates to this
namespace /* Enclosing */ {
using Sibling1::cos;
namespace Sibling2 {
float f(float x) { return cos(x); }
};
}
The namespace I marked as enclosing is either Base or the global namespace. The "kinda" bit (according to paragraph 3) is that it's not an actual declaration being added. I.e. if something named cos already exists in /* Enclosing */, it's not a re-declaration. This is by design, because using directives can potentially bring a lot of names in, and so it shouldn't cause an error when the names they bring are not actually used.
In your case however, the name brought in is used.
When /* Enclosing */ is Base, it matches only one declaration, the one in Sibling1, as-if it was declared in Base.
When /* Enclosing */ is the global namespace, it matches the actual declaration there too, presumably the one brought in by math.h (you seem to be using that). So you get an ambiguity (the name refers to two potential entities).
So on the whole, compilers that reject this code are behaving as expected. While I understand your plight, I don't think there's really a problem for you to solve here. If client code finds Base::Sibling1::cos too verbose, it itself can employ a using directive of the form using namespace Base;. Or using a namespace alias to shorten things namespace sib1 = Base::Sibling1;.
The problem cannot be reproduced as you describe it. Moreover, there is no reason that the flattening alone introduces ambiguities, if you use expose in the siblings the same names you introduced in Base. So, the root cause is probably in some parts of the code you are not showing.
The second version does not define cosf(), so you probably are using some namespace. If in that namespae there is also a cos() you create an ambiguity between the two overloads. I could reproduce this by using namespace std:
#include <iostream>
#include <cmath>
using namespace std;
namespace Sibling1 {
float cos(float x) { return cosf(x); }
}
namespace Sibling2 {
using namespace Sibling1;
float f(float x) { return cos(x); }
}
Online demo: the compilation error indicates which are the candidates behind the ambiguity. If you now comment the using namespace out, the ambiguity goes away, and the code compiles. Online proof.
Namespaces are meant to avoid naming conflicts and keep control of ambiguities:
Creating a namespace and systematically using namespace everywhere defeats the whole purpose.
On the other side, long using lists are painful to maintain, especially if you have to repeat them in several sibling namespaces. This is probably why the Base and the nesting were created in the first place.
In the first version, you do not show what's in Base. It is possible that some more tailored using clauses are used therein instead of full namespaces: if selectively injecting the really required functions in the Base namespace, they are made available within the siblings avoiding ambiguity that can be introduced by injecting the name of unnecessary functions.

so I decided to not use namespace anymore, but now when should I add std:: or cv::?

I recently started using c++ and opencv for image processing. since the beginning almost every sample code had using namespace std; in the header. after reading about it I saw that it is recommended not to use namespace since it can lead to problems when two libraries have the same function name.
so I changed it and used cv:: and std:: whenever I got an error but still there were functions from opencv that had no error I assume this is because there's only one function with that name. but should I add the identifier for every function even if this doesn't lead to an error?
for example
cv::Mat antif;
idft(complexI, antif);
split(antif, planes);
magnitude(planes[0], planes[1], antif);
normalize(antif, antif, 0, 1, cv::NORM_MINMAX);
I'm measuring the phase difference between two images using Fourier transform.
I had to add cv:: when making the variable antif. but no error popped up for any of the following functions included in opencv.
is this because there is only one instance of this questions or should I add cv:: just to get used to doing so?
ADL has been mentioned in another answer.
Here's how it works:
In the example below, notice that the function show has been defined in namespaces Foo and Bar.
ADL allows the compiler to look in all namespaces mentioned in the argument list.
x1 is a Foo::X so in the first call to show() the following namespaces may be checked:
Foo
:: (the global namespace)
any namespace pulled into Foo with a using namespace
any namespace pulled into the global namespace with a using namespace (which is why we don't use using namespace in the global namespace)
#include <iostream>
namespace Foo
{
struct X{};
void show(X const&)
{
std::cout << "a Foo::X" << std::endl;
}
}
namespace Bar
{
struct X{};
void show(X const&)
{
std::cout << "a Bar::X" << std::endl;
}
}
int main()
{
auto x1 = Foo::X();
auto x2 = Bar::X();
show(x1);
show(x2);
}
expected output:
a Foo::X
a Bar::X
These functions are found by argument-dependent lookup. So, they are in the cv namespace, but the compiler is able to guess this because the type of (at least) one of the arguments is in the cvnamespace.

How to overcome the namespace evil of C++ header files?

With one of my projects I will head into the C++ field. Basically I am coming
from a Java background and was wondering how the concept of Java packages
is realized in the C++ world. This led me to the C++ concept of namespaces.
I am absolutely fine with namespaces so far but when it comes to header files
things are becoming kind of inefficient with respect to fully qualified class
names, using-directives and using-declarations.
A very good description of the issue is this article by Herb Sutter.
As I understand it this all boils down to: If you write a header file always
use fully qualified type names to refer to types from other namespaces.
This is almost unacceptable. As a C++ header commonly provides the declaration
of a class, a maximum of readability has top priority. Fully qualifying each
type from a different namespace creates a lot of visual noise, finally
diminishing readability of the header to a degree which raises the question
whether to use namespaces at all.
Nevertheless I want to take advantage of C++ namespaces and so put some thought into
the question: How to overcome the namespace evil of C++ header files? After
some research I think typedefs could be a valid cure to this problem.
Following you will find a C++ sample program which demonstrates how I would
like to use public class scoped typedefs to import types from other namespaces.
The program is syntactically correct and compiles fine on MinGW W64. So far so
good, but I am not sure whether this approach happily removes the using keyword
from the header but brings in another problem which I am simply not aware of.
Just something tricky like the things described by Herb Sutter.
That is I kindly ask everybody who has a thorough understanding of C++ to
review the code below and let me know whether this should work or not. Thanks
for your thoughts.
MyFirstClass.hpp
#ifndef MYFIRSTCLASS_HPP_
#define MYFIRSTCLASS_HPP_
namespace com {
namespace company {
namespace package1 {
class MyFirstClass
{
public:
MyFirstClass();
~MyFirstClass();
private:
};
} // namespace package1
} // namespace company
} // namespace com
#endif /* MYFIRSTCLASS_HPP_ */
MyFirstClass.cpp
#include "MyFirstClass.hpp"
using com::company::package1::MyFirstClass;
MyFirstClass::MyFirstClass()
{
}
MyFirstClass::~MyFirstClass()
{
}
MySecondClass.hpp
#ifndef MYSECONDCLASS_HPP_
#define MYSECONDCLASS_HPP_
#include <string>
#include "MyFirstClass.hpp"
namespace com {
namespace company {
namespace package2 {
/*
* Do not write using-declarations in header files according to
* Herb Sutter's Namespace Rule #2.
*
* using std::string; // bad
* using com::company::package1::MyFirstClass; // bad
*/
class MySecondClass{
public:
/*
* Public class-scoped typedefs instead of using-declarations in
* namespace package2. Consequently we can avoid fully qualified
* type names in the remainder of the class declaration. This
* yields maximum readability and shows cleanly the types imported
* from other namespaces.
*/
typedef std::string String;
typedef com::company::package1::MyFirstClass MyFirstClass;
MySecondClass();
~MySecondClass();
String getText() const; // no std::string required
void setText(String as_text); // no std::string required
void setMyFirstInstance(MyFirstClass anv_instance); // no com::company:: ...
MyFirstClass getMyFirstInstance() const; // no com::company:: ...
private:
String is_text; // no std::string required
MyFirstClass inv_myFirstInstance; // no com::company:: ...
};
} // namespace package2
} // namespace company
} // namespace com
#endif /* MYSECONDCLASS_HPP_ */
MySecondClass.cpp
#include "MySecondClass.hpp"
/*
* According to Herb Sutter's "A Good Long-Term Solution" it is fine
* to write using declarations in a translation unit, as long as they
* appear after all #includes.
*/
using com::company::package2::MySecondClass; // OK because in cpp file and
// no more #includes following
MySecondClass::MySecondClass()
{
}
MySecondClass::~MySecondClass()
{
}
/*
* As we have already imported all types through the class scoped typedefs
* in our header file, we are now able to simply reuse the typedef types
* in the translation unit as well. This pattern shortens all type names
* down to a maximum of "ClassName::TypedefTypeName" in the translation unit -
* e.g. below we can simply write "MySecondClass::String". At the same time the
* class declaration in the header file now governs all type imports from other
* namespaces which again enforces the DRY - Don't Repeat Yourself - principle.
*/
// Simply reuse typedefs from MySecondClass
MySecondClass::String MySecondClass::getText() const
{
return this->is_text;
}
// Simply reuse typedefs from MySecondClass
void MySecondClass::setText(String as_text)
{
this->is_text = as_text;
}
// Simply reuse typedefs from MySecondClass
void MySecondClass::setMyFirstInstance(MyFirstClass anv_instance)
{
this->inv_myFirstInstance = anv_instance;
}
// Simply reuse typedefs from MySecondClass
MySecondClass::MyFirstClass MySecondClass::getMyFirstInstance() const
{
return this->inv_myFirstInstance;
}
Main.cpp
#include <cstdio>
#include "MySecondClass.hpp"
using com::company::package2::MySecondClass; // OK because in cpp file and
// no more #includes following
int main()
{
// Again MySecondClass provides all types which are imported from
// other namespaces and are part of its interface through public
// class scoped typedefs
MySecondClass *lpnv_mySecCls = new MySecondClass();
// Again simply reuse typedefs from MySecondClass
MySecondClass::String ls_text = "Hello World!";
MySecondClass::MyFirstClass *lpnv_myFirClsf =
new MySecondClass::MyFirstClass();
lpnv_mySecCls->setMyFirstInstance(*lpnv_myFirClsf);
lpnv_mySecCls->setText(ls_text);
printf("Greetings: %s\n", lpnv_mySecCls->getText().c_str());
lpnv_mySecCls->setText("Goodbye World!");
printf("Greetings: %s\n", lpnv_mySecCls->getText().c_str());
getchar();
delete lpnv_myFirClsf;
delete lpnv_mySecCls;
return 0;
}
Pain is mitigated by reducing complexity. You're bending C++ into Java. (That works just as bad as trying the other way.)
Some hints:
Remove the "com" namespace level. (This is just a java-ism that you don't need)
Drop the "company" namespace, maybe replace by "product" or "library" namespace (i.e. boost, Qt, OSG, etc). Just pick something that's unique w.r.t. the other libs you're using.
You don't need to fully declare names that are in the same namespace you're in (caveat emptor: template classe, see comment). Just avoid any using namespace directives in the headers. (And use with care in C++ files, if at all. Inside functions is preferred.)
Consider namespace aliases (in functions/cpp files), i.e namespace bll = boost::lambda;. This creates shortcuts that are quite neat.
Also, by hiding private members/types using the pimpl pattern, your header have less types to expose.
P.S: Thanks to #KillianDS a few good tips in comments (that were deleted when I edited them into the question.)