how to use pointer of one namespace in another namespace nad both the namespace are used in another class - c++11

Below is my sample code where we are facing the issue
file1.h
namespace name1
{
extern name1::test* _test;
}
file2.h
namespace name2
{
class toolbox
{
int fun()
{
return _test->test();
}
}
}
newfile.cpp
using namespace name1;
using namespace name2;
int newclass::new()
{
return _test->test();
}
With above I will get error :
undefined reference to name2::_test
If I add extern in name2 I get error :
_test ambiguous

The problem you have are conflicting symbols between the namespaces that you are using.
This is a typical example used in styleguides which forbid using namespace.
Instead of including the whole namespace, you could prefix the identifiers with NS::, for example: name1::_test.
Alternatively, it is possible to selectively use elements from the namespace by using: using NS::Identifier. However, I never found myself in a situation where I needed on a global, so don't know if this works.
A piece of advice: don't use global variables, it is much more maintainable to pass the pointers or references as arguments for your functions.

Related

C++ using namespaces for versioning can cause inheritance problems with overrides

We are trying to namespace the versions of our API with namespaces, although we figured that we will be getting some problems with virtual functions :
namespace v1 {
class someParam {
public:
someParam() {};
virtual ~someParam() {};
};
class someClass {
public:
someClass() {};
virtual ~someClass() {};
virtual bool doSomething(someParam a);
};
bool someClass::doSomething(someParam a)
{
return true;
}
}
namespace v2 {
class someParam : public v1::someParam {
public:
bool doParamStuff();
};
bool someParam::doParamStuff()
{
return true;
}
}
// Type Aliasing for v2 API
using someClass = v1::someClass;
using someParam = v2::someParam;
// SOME OTHER PROGRAM
class plugin : public someClass
{
public:
plugin() {};
virtual ~plugin() {};
bool doSomething(someParam a) override;
};
In this specific case, we are creating extension of existing classes to allow binary compatibility. Although, we get a compilation error for plugin::doSomething because of the override keyword as it is not overriding someClass::doSomething because:
plugin::doSomething(v2::someParam) vs someClass::doSomething(v1::someParam).
Is there any way to fix up the plugin without explicitely using v1 for someParam in plugin class ? Ideally, nothing should be done on the plugin side, and without having to create v2::someClass
This:
virtual bool doSomething(::v1::someParam a)
specifies a binary (and C++) interface. You cannot override it with
virtual bool doSomething(::v2::someParam a)
as that is a different type. They are not compatible. These signatures are unrelated.
When you update someParam, you must also update every interface that uses someParam, and then every interface that uses those interfaces, etc.
So, in namespace v2:
class someClass: ::v1::someClass {
public:
virtual bool doSomething(::v1::someParam a) override final;
virtual bool doSomething(someParam a);
};
and in doSomething(v1::someParam) describe how to generate a v2::someParam and pass it to the new doSomething.
If you cannot do this, you instead have to do this:
class someClass {
public:
virtual bool doSomething(someParam a);
};
and make v2::someClass a type unrelated to v1::someClass.
Regardless, you do
using someClass = v2::someClass;
Now, instead of using using declarations, you can instead conditually use inline namespaces.
When you update a version, make the current version the inline namespace. The others are normal namespaces.
Code will now silently start using the inline namespace that is "current".
You can import types from previous namespaces by using symbol = ::library_ns::v1::symbol; This should only be done when that type is unchanged, as well as all of its parameters.
Now, if your ::v2::someParam is only a helper, you can split someParamArg from someParamInstance types.
someParamArg would then be the argument type of the root of the someParam heirarchy (::v1::someParam), while someParamInstance would be ::v2::someParam; what people should create when they want to use it.
In this case, someParamArg needs to be able to consider every state of someParamInstance, even those from later versions. Hence this only works if ::v2::someParam is essentially a helper, or if it supports internal value-type polymorphism.

where should I put the specialized std::hash for user defined type

I searched many pages, and I think I have known how to write the std::hash. But I don't know where to put it.
An example is presented here http://en.cppreference.com/w/cpp/utility/hash .
However, I defined my type Instance in namespace ca in file instance_management.h. I want to use unordered_set<Instance> in the same file in another class InstanceManager. So I write the following code:
namespace std
{
template <> struct hash<ca::Instance>
{
size_t operator()(const ca::Instance & instance) const
{
std::size_t seed = 0;
// Some hash value calculation here.
return seed;
}
};
} // namespace std
But where should I put it? I tried many locations but all failed.
I am using visual studio 2013. I tried to put the previous code in some locations but all failed to compile it.
// location 1
namespace ca
{
class Instance {...}
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
// location 2
There are several ways.
Specializing std::hash
In your code make sure that your std::hash<Instance> specialization is preceded immediately by the Instance class definition, and followed by the use of the unordered_set container that uses it.
namespace ca
{
class Instance {...};
}
namespaces std {
template<> hash<Instance> { ... };
}
namespace ca {
class InstanceManager
{
// ... some other things.
private unordered_set<Instance>;
}
}
One drawback is that you can have funny name lookup interference when passing a std::hash<ca::Instance> to other functions. The reason is that the associated namespace (ca) of all the template arguments of std::hash can be used during name lookup (ADL). Such errors are a bit rare, but if they occur they can be hard to debug.
See this Q&A for more details.
Passing your hash to unordered_set
struct MyInstanceHash { ... };
using MyUnorderedSet = std:unordered_set<Instance, MyInstanceHash>;
Here, you simply pass your own hash function to the container and be done with it. The drawback is that you have to explicitly type your own container.
Using hash_append
Note, however, there is the N3980 Standard proposal is currently pending for review. This proposal features a much superior design that uses a universal hash function that takes an arbitrary byte stream to be hashed by its template parameter (the actual hashing algorithm)
template <class HashAlgorithm>
struct uhash
{
using result_type = typename HashAlgorithm::result_type;
template <class T>
result_type
operator()(T const& t) const noexcept
{
HashAlgorithm h;
using std::hash_append;
hash_append(h, t);
return static_cast<result_type>(h);
}
};
A user-defined class X then has to provide the proper hash_append through which it presents itself as a byte stream, ready to be hashed by the univeral hasher.
class X
{
std::tuple<short, unsigned char, unsigned char> date_;
std::vector<std::pair<int, int>> data_;
public:
// ...
friend bool operator==(X const& x, X const& y)
{
return std::tie(x.date_, x.data_) == std::tie(y.date_, y.data_);
}
// Hook into the system like this
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
using std::hash_append;
hash_append(h, x.date_);
hash_append(h, x.data_);
}
}
For more details, see the presentation by the author #HowardHinnant at CppCon14 (slides, video). Full source code by both the author and Bloomberg is available.
Do not specialise std::hash, instead write your own hash function object (see Edge_Hash below) and declare your unordered_set with two template arguments.
#include <unordered_set>
#include <functional>
namespace foo
{
// an edge is a link between two nodes
struct Edge
{
size_t src, dst;
};
// this is an example of symmetric hash (suitable for undirected graphs)
struct Edge_Hash
{
inline size_t operator() ( const Edge& e ) const
{
static std::hash<size_t> H;
return H(e.src) ^ H(e.dst);
}
};
// this keeps all edges in a set based on their hash value
struct Edge_Set
{
// I think this is what you're trying to do?
std::unordered_set<Edge,Edge_Hash> edges;
};
}
int main()
{
foo::Edge_Set e;
}
Related posts are, eg:
Inserting in unordered_set using custom hash function
Trouble creating custom hash function unordered_map
Thanks to everyone.
I have found the reason and solved the problem somehow: visual studio accepted the InstanceHash when I was defining instances_. Since I was changing the use of set to unordered_set, I forgot to specify InstanceHash when I tried to get the const_iterator, so this time the compiler tried to use the std::hash<> things and failed. But the compiler didn't locate the line using const_iterator, so I mistakenly thought it didn't accept InstanceHash when I was defining instances_.
I also tried to specialize the std::hash<> for class Instance. However, this specialization requires at least the declaration of class ca::Instance and some of its member functions to calculate the hash value. After this specialization, the definition of class ca::InstanceManage will use it.
I now generally put declarations and implementations of almost every classes and member functions together. So, the thing I need to do is probably to split the ca namespace scope to 2 parts and put the std{ template <> struct hash<ca::Instance>{...}} in the middle.

Class-Wide `using` alias as return type issuing compiler error

In order to keep some code readable and avoid typos, I'm using the following statement in the public section of a class definition in a header file:
using Assembly_Tuple = std::tuple <std::vector <std::string>, Trigger_Map, Attribute_Map>;
I'm declaring a function in the header file with Assembly_Tuple as a return type:
Assembly_Tuple merge_node_attributes(const std::string& node_name, std::string tmpl_name="");
And I'm defining the function in the source file:
Widget_Server_Interface::Assembly_Tuple
Widget_Server_Interface::merge_node_attributes(const std::string& n, const std::string& t)
{
//...
}
But when I try to compile, I get the following error:
src/WidgetServer/WidgetServerInterface.cpp:31:1: error: ‘Assembly_Tuple’ in ‘class Widget_Server_Interface’ does not name a type
However, inside definitions, there aren't any problems.
If I change that line to the egregious:
std::tuple<std::vector<std::string>, Trigger_Map, std::map<int,Node_Value>>
Widget_Server_Interface::merge_node_attributes (...) {...}
it's fine. Clearly the problem is using the alias outside of scope, even though it's public
and I'm explicitly calling on the class namespace.
I looked in Bjarne's book but he doesn't mention anywhere whether or not this is legal.
This is using gcc 4.7.
Mostly, I would just like to know why this isn't valid.

Replacement of Poco::AutoPtr with boost

I am trying to replace Poco::AutoPtr with some alternative in boost. Here is what I have discovered so far:
What I have: below classess are being used with Poco::AutoPtr. They need to implement reference counted method with implementing duplicate() and release() methods.
I am using above referece_counted.h and Poco::AutoPtr in a complex class hierarchy with multiple inheritance and c++ diamond problems.
A simplified version of classes would look something like this
class A : virtual public ReferenceCounted
{
...
}
class B : public A
{
...
}
class C : public A
{
...
}
class D : public A, B
{
...
}
and the list goes on for few more level deep. I know that this needs to be refactored with a simplified hierarchy but I wanna remove Poco::AutoPtr first with proper replacement in boost:
What I have found so far:
I have found that boost::intrusive_ptr is the closest smart pointer that can be a good replacement of Poco::AutoPtr.
I am however not able to implement the proper solution with this because the intrusive_ptr requires intrusive_ptr_add_ref and intrusive_ptr_release methods created specifically for each class with which I need to use the pointer. I tried using templates but still not having proper solution at hand.
Also one more issue is that I need to typecast from base to derived class many times.
is intrusive_ptr is the correct smart pointer for this usage ? and if yes.. can anybody give me suggestion regarding how to use the same ?
I am however not able to implement the proper solution with this
because the intrusive_ptr requires intrusive_ptr_add_ref and
intrusive_ptr_release methods created specifically for each class with
which I need to use the pointer.
No-no. It is should not be hard. As Boost documentation says:
On compilers that support argument-dependent lookup,
intrusive_ptr_add_ref and intrusive_ptr_release should be defined in
the namespace that corresponds to their parameter; otherwise, the
definitions need to go in namespace boost.
Try this: main.cpp (built ok with "g++ main.cpp -o main -lboost_system")
#include <boost/intrusive_ptr.hpp>
class MyObject
{
public:
void duplicate(){
// ...
}
void release(){
// ...
}
};
namespace boost {
template <class T>
void intrusive_ptr_add_ref( T * po ) {
po->duplicate(); // your internal realization
}
template <class T>
void intrusive_ptr_release( T * po ) {
po->release();
}
}
int main(int argc, char **argv)
{
// ...
boost::intrusive_ptr<MyObject> ptr( new MyObject );
boost::intrusive_ptr<MyObject> ptr2 = ptr; // should work
}

typedef struct syntax for C++ Windows Forms?

i'm having trouble with syntax regarding c++ Windows Forms..
this is how you obviously do it in a regular cpp project: http://www.cplusplus.com/doc/tutorial/structures/
but its not the same in windows forms :/
any help??
THANKS!
btw, i figured it out!
you must create a new class in the project...
call it, Player.h
in the new class, you must instantiate the class like below
to make it a managed class so it fits well with the managed code
in the forms (notice ref class keyword)
struct markedPos
{
int xPos;
int yPos;
};
ref class Player
{
public:
Player()
{
}
protected:
private:
};
then simply in the forms.h file, you must include the new class like any other class:
#include "Player.h"
and all you have to do is make an instance of the player in your forms and it'll work like magic! What i've learned: Do all your heavy lifting in the managed classes outside of the forms... which work just like your regular c++ classes...
cheers!
** You don't need to use managed code! if your getting problems with it, just remove 'ref' before class name

Resources