C++ static list with private constructor - c++

I apologize if this has been asked, I'm not sure how one best words it and couldn't really find it.
I essentially have a class that I want to maintain a map of itself, and that list should have the only instantiations of the object.
using std::unordered_map;
class MyClass
{
~MyClass() {};
MyClass() {}; // these actually contain code which operate on the classes data
static unordered_map<Uint32, MyClass> list;
public:
static const MyClass& GetObject(Uint32 key) {return list[key];};
};
When i compile my code it basically gives me a bunch of errors from the STL saying it's calling deleted functions and such, which makes sense because unordered_map probably uses the constructor and destructor, so I declared unordered_map a friend
friend class unordered_map<Uint32, MyClass>;
However there doesn't seem to be any fewer errors, which I speculate is due to classes used by unordered_map like pair, and hash. So my question is if there is an alternative to this. Should I just declare more things friends that appear to be giving errors in from the compiler, or is there another method?

So. You're in the mood to do something annoying. So let's do it. As AlexD says, what you're missing is a public destructor. The unordered_map needs access to this (possibly through some implementation defined inner class).
So let's do that, and let's do what you should have done in the first place, which is to make a much smaller and simpler test case:
#include <unordered_map>
class MyClass {
public:
~MyClass() {}
private:
MyClass() {}
};
int main() {
std::unordered_map<int, MyClass> x;
x.at(3);
//x[3];
}
Now that compiles fine.
Now, note that I have commented out x[3]. We can't use that. That's because if 3 doesn't exist in the map, we'd call the default constructor of MyClass, which is private. And because the compiler doesn't know at compile time if that's true, it will need to ensure that it could call the constructor.
From the comments, there's a concern that you couldn't insert any objects into this map. Well, let's add a static factory method and get rid of that concern:
#include <unordered_map>
using std::unordered_map;
class MyClass {
public:
static MyClass factory() { return MyClass(); }
~MyClass() {}
private:
MyClass() {}
int x;
};
int main() {
std::unordered_map<int, MyClass> x;
x.insert(std::make_pair(3, MyClass::factory()));
x.emplace(4, MyClass::factory());
}

UPDATE: T.C. kindly pointed out a couple things I'd overlooked, so this answer's done a complete about-face....
#include <iostream>
#include <unordered_map>
#include <map>
#include <cinttypes>
class MyClass
{
typedef std::unordered_map<uint32_t, MyClass> Instances;
friend Instances;
friend std::pair<uint32_t, MyClass>;
friend std::pair<const uint32_t, MyClass>;
public:
static const MyClass& getObject(uint32_t key) { return instances_[key] = 2 * key; }
~MyClass() {}
int n() const { return n_; }
private:
MyClass() : n_(-1) { }
MyClass& operator=(int n) { n_ = n; return *this; }
int n_;
static Instances instances_;
};
MyClass::Instances MyClass::instances_;
int main() {
const MyClass& m20 = MyClass::getObject(20);
const MyClass& m21 = MyClass::getObject(21);
std::cout << m20.n() << ' ' << m21.n() << '\n';
}
Above code at ideone.com.
As per comments, the list of necessary friendship isn't documented by the Standard, so could break with new compiler versions or when porting to another compiler.
Alterantively, you can store (smart) pointers in the unordered_map.

Related

Calling a function from another class from within an unordered_multimap?

This is related to my last post that you can find here: Creating an unordered_map of std::functions with any arguments. I have now gone ahead and extended this out to classes. So let's say I have three different classes. And these classes all have different methods except for getVariable() and setVariable(int). So for this example we will class them ClassA, ClassB, and ClassC.
I also have a base class which I want to use as my driver. Essentially, if I want to set the variable between ClassA and ClassC I would call the base class' setVariable function.
#ifndef BASE_CLASS_HPP
#define BASE_CLASS_HPP
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
// return classA and ClassB's values
}
void setValue(int newVal)
{
auto iter = functions.equal_range("setValue");
std::any_cast<void(*)(int)>(mapIter->second)(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
};
I then have in main:
#include <iostream>
#include "baseClass.hpp"
#include "classA.hpp"
#include "classB.hpp"
#include "classC.hpp"
int main()
{
ClassA a;
ClassB b;
ClassC c;
c.setValue(20);
BaseClass<ClassA,ClassB> base1;
BaseClass<ClassA,ClassC> base2;
base1.setValue(15);
auto values = base1.getValues();
}
I can place the functions withing my map, however, when I try to any_cast I don't get anything in return. I also tried:
std::any_cast<void(A::*)(int)>(mapIter->second)(newVal);
But that also gives me a compiler error of must use .* or ->* and I have tried everything to get it to compile and I don't really know what I am doing wrong. I also realized, if I called it that way, then I wouldn't be able to access B's setVariable function since I am using A's namespace.
Is there anyway I can get this to work how I want it to? I am essentially trying to modify those class values without having to make any copies of those classes and instead directly modify them from within this driver.
I still don't quite understand the purpose of such structure, but here an option how to make it at least compile:
#include <unordered_map>
#include <functional>
#include <utility>
#include <string>
#include <any>
template<class A, class B>
class BaseClass
{
public:
BaseClass() { bindThem(); }
std::pair<int,int> getValue()
{
auto range = functions.equal_range("getValue");
return
{
(a.*std::any_cast<int(A::*)()>(*range.first))(),
(b.*std::any_cast<int(B::*)()>(*range.second))()
};
}
void setValue(int newVal)
{
auto range = functions.equal_range("setValue");
(a.*std::any_cast<void(A::*)(int)>(*range.first))(newVal);
(b.*std::any_cast<void(B::*)(int)>(*range.second))(newVal);
}
private:
std::unordered_multimap<std::string,std::any> functions;
void bindThem()
{
functions.emplace("setValue",&A::setValue);
functions.emplace("setValue",&B::setValue);
functions.emplace("getValue",&A::getValue);
functions.emplace("getValue",&B::getValue);
}
A a;
B b;
};
class ClassA
{
public:
void setValue(int){}
int getValue() {return 0;}
};
class ClassB
{
public:
void setValue(int){}
int getValue() {return 1;}
};
int main()
{
BaseClass<ClassA, ClassB> x;
x.setValue(3);
auto i = x.getValue();
}
Please note several things:
I've added members to BaseClass since to call member functions you need an object to be called on.
I'm using first and last iterators of the range from equal_range, but the order of elements in that range is implementation defined. So to make things work you need to take care of distinguishing which container element corresponds to class A and which to class B.

How to create a private static const string when using the pimpl idiom

Background
I have been learning how to implement the pimpl idiom using the newer c++11 method described by Herb Sutter at this page: https://herbsutter.com/gotw/_100/
I'm trying to modify this example by adding a member variable to the private implementation, specifically a std::string (although a char* has the same issue).
Problem
This seems to be impossible due to the use of a static const non-integral type. In-class initialization can only be done for integral types, but because it is static it can't be initialized in the constructor either.
A solution to this problem is to declare the private variable in the header file, and initialize it in the implementation, as shown here:
C++ static constant string (class member)
However, this solution does not work for me because it breaks the encapsulation I'm trying to achieve through the pimpl idiom.
Question
How can I hide a non-integral static const variable within the hidden inner class when using the pimpl idiom?
Example
Here is the simplest (incorrect) example I could come up with demonstrating the problem:
Widget.h:
#ifndef WIDGET_H_
#define WIDGET_H_
#include <memory>
class Widget {
public:
Widget();
~Widget();
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
#endif
Widget.cpp:
#include "Widget.h"
#include <string>
class Widget::Impl {
public:
static const std::string TEST = "test";
Impl() { };
~Impl() { };
};
Widget::Widget() : pimpl(new Impl()) { }
Widget::~Widget() { }
Compilation command:
g++ -std=c++11 -Wall -c -o Widget.o ./Widget.cpp
Note that this example fails to compile because the variable TEST cannot be assigned at declaration due to it not being an integral type; however, because it is static this is required. This seems to imply that it cannot be done.
I've been searching for previous questions/answers to this all afternoon, but could not find any that propose a solution that preserves the information-hiding property of the pimpl idiom.
Solution Observations:
In my example above, I was attempting to assign the value of TEST in the Impl class declaration, which is inside of Widget.cpp rather than its own header file. The definition of Impl is also contained within Widget.cpp, and I believe this was the source of my confusion.
By simply moving the assignment of TEST outside of the Impl declaration (but still within the Widget/Impl definition), the problem appears to be solved.
In both of the example solutions below, TEST can be accessed from within Widget by using
pimpl->TEST
Attempting to assign a different string into TEST, i.e.
pimpl->TEST = "changed"
results in a compiler error (as it should). Also, attempting to access pimpl->TEST from outside of Widget also results in a compiler error because pimpl is declared private to Widget.
So now TEST is a constant string which can only be accessed by a Widget, is not named in the public header, and a single copy is shared among all instances of Widget, exactly as desired.
Solution Example (char *):
In the case of using a char *, note the addition of another const keyword; this was necessary to prevent changing TEST to point to another string literal.
Widget.cpp:
#include "Widget.h"
#include <stdio.h>
class Widget::Impl {
public:
static const char *const TEST;
Impl() { };
~Impl() { };
};
const char *const (Widget::Impl::TEST) = "test";
Widget::Widget() : pimpl(new Widget::Impl()) { }
Widget::~Widget() { }
Solution Example (string):
Widget.cpp:
#include "Widget.h"
#include <string>
class Widget::Impl {
public:
static const std::string TEST;
Impl() { };
~Impl() { };
};
const std::string Widget::Impl::TEST = "test";
Widget::Widget() : pimpl(new Widget::Impl()) { }
Widget::~Widget() { }
Update:
I realize now that the solution to this problem is completely unrelated to the pimpl idiom, and is just the standard C++ way of defining static constants. I've been used to other languages like Java where constants have to be defined the moment they are declared, so my inexperience with C++ prevented me from realizing this initially. I hope this avoids any confusion on the two topics.
#include <memory>
class Widget {
public:
Widget();
~Widget();
private:
class Impl;
std::unique_ptr<Impl> pimpl;
};
/*** cpp ***/
#include <string>
class Widget::Impl {
public:
static const std::string TEST;
Impl() { };
~Impl() { };
};
const std::string Widget::Impl::TEST = "test";
Widget::Widget() : pimpl(new Impl()) { }
Widget::~Widget() { }
You might want to consider making TEST a static function which returns a const std::string&. This will allow you to defined it inline.
You could also replace const by constexpr in your example and it will compile.
class Widget::Impl {
public:
static constexpr std::string TEST = "test"; // constexpr here
Impl() { };
~Impl() { };
};
Update:
Well, it seems that I was wrong... I always store raw string when I want constants.
class Widget::Impl {
public:
static constexpr char * const TEST = "test";
};
Depending on the usage pattern, it might be appropriate or not. If not, then define the variable as explained in the other answer.

How can I access a protected constructor from a friend function?

I created a class and I want to force anyone who's trying to construct an object, to use unique_ptr. To do that I thought of declaring the constructor protected and use a friend function that returns a unique_ptr. So here's an example of what I want to do:
template <typename T>
class A
{
public:
friend std::unique_ptr<A<T>> CreateA<T>(int myarg);
protected:
A(int myarg) {}
};
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
// Since I declared CreateA as a friend I thought I
// would be able to do that
return std::make_unique<A<T>>(myarg);
}
I did some reading on friend functions and I understood that a friend function provides access to private/protected members of an object of a class.
Is there anyway I can make my example work?
Even without friend functions, my goal is to make the CreateA the only way for someone to create an object.
EDIT
I change the code a bit. I didn't mention that my class takes one template parameter. That makes things more complex apparently.
You can do it this way :-
#include <iostream>
#include <memory>
using namespace std;
class A
{
int arg;
public:
friend unique_ptr<A> CreateA(int myarg);
void showarg() { cout<<arg; }
protected:
A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
return std::unique_ptr<A>(new A(myarg));
}
int main()
{
int x=5;
unique_ptr<A> u = CreateA(x);
u->showarg();
return 0;
}
Output :-
5
If you don't want to use friend function you can make the function static & call it like this :-
unique_ptr<A> u = A::CreateA(x);
EDIT :-
In reply to your edit I rewrote the program & it goes like this :-
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
T arg;
public:
static std::unique_ptr<A> CreateA(T myarg)
{
return std::unique_ptr<A>( new A(myarg) );
}
void showarg()
{
cout<<arg;
}
protected:
A(T myarg): arg(myarg) {}
};
int main()
{
int x=5;
auto u = A<int>::CreateA(x);
u->showarg();
return 0;
}
Simple & easy !!! But remember you cannot instantiate the object of A. Good Luck !!!
The other answers suggest using a static template function, which I agree is the best solution, because it is simpler.
My answer explains why your friend approach didn't work and how to use the friend approach correctly.
There are two problems in your original code. One is that make_unique is not actually a friend of A, so the call make_unique<A<T>>(myarg); does not have access to A's protected constructor. To avoid this , you can use unique_ptr<A<T>>(new A(myarg)) instead. Theoretically it would be possible to declare make_unique a friend but I'm not even sure of the right syntax for that.
The other issue is the template friends problem. Inside a class template, friend <function-declaration> actually declares a non-template friend.
The C++ FAQ suggests two possible workarounds. One of them is to define the friend function inline. However, in that case the function can only be found by argument-dependent lookup. But since the function does not take A<T> (or A<T> &) as argument, it can never be found this way. So this option is not viable to your situation -- it's more suited to operator overloading.
So the only fix is to declare (and optionally define) the template function before the class definition:
#include <memory>
template<typename T>
class A;
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
return std::unique_ptr<A<T>>{new A<T>(myarg)};
}
template <typename T>
class A
{
friend std::unique_ptr<A<T>> CreateA <> (int myarg);
// refers to existing template ^^
protected:
A(int myarg) {}
};
int main()
{
auto x = CreateA<int>(5);
}
Note: It is possible to declare CreateA where I have defined it, and put the function definition later. However, the code I have posted works -- despite A not being defined when new A<T>(myarg) appears in the source -- because CreateA is not instantiated until it is called, at which point A will be defined.
Create a static function that instantiates the protected constructor.
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
std::unique_ptr<A<T>> objB(new A(myarg, t));
objA = std::move(objB);
}
protected:
A(int myarg, T t) {
m_t = t;
}
private:
T m_t;
};
int main() {
int myArg = 0;
std::unique_ptr<A<int>> anotherObjA;
A<int>::CreateA(myArg, anotherObjA, myArg);
return 0;
}

Is it possible to write an agile Pimpl in c++?

I've been playing with the Pimpl idiom and reaping all sorts of benefits from it. The only thing I haven't been too keen on is the feeling I get when I define the functions.
Once in the header (P def)
Once at the top of the .cpp (Impl def)
Once in the middle of the .cpp (Impl Impl)
Once at the lower end of the .cpp (P Impl)
I really enjoy cutting down code disparity and redundancy, and I feel like my code is less than well oiled when I have to add or change functions in even relatively complex Impls in my current project.
My question is, what effective ways are there to imply or template my classes in such a way that if I were to define a new function, I'd only have to write one explicit definition and implementation, and have the rest remain spatially close to the explicits in code; and if I were to change a function, the changes necessary would be as few as possible?
You might consider something along these lines:
An Interface class to minimize repeating declarations. The client will use the PublicImplementation class in their code.
Pimpl.h
#ifndef PIMPL_H_
#define PIMPL_H_
#include <memory> // std::unique_ptr
class Interface
{
public:
virtual ~Interface() {}
virtual void func_a() = 0;
virtual void func_b() = 0;
};
class PublicImplementation
{
// smart pointer provides exception safety
std::unique_ptr<Interface> impl;
public:
PublicImplementation();
// pass-through invoker
Interface* operator->() { return impl.get(); }
};
#endif // PIMPL_H_
Pimpl.cpp
#include "Pimpl.h"
#include <iostream>
class PrivateImplementation
: public Interface
{
public:
void func_a() override { std::cout << "a" << '\n'; }
void func_b() override { std::cout << "b" << '\n'; }
};
PublicImplementation::PublicImplementation()
: impl(new PrivateImplementation)
{
}
And finally this is what the client code does:
Main.cpp
#include "Pimpl.h"
int main()
{
PublicImplementation pi; // not a pointer
pi->func_a(); // pointer semantics
pi->func_b();
}
Let's postulate your header starts something like this:
class X
{
public:
...la de dah...
private:
struct Impl;
Impl* p_impl_;
};
Then when you add functions you have a choice to make:
do you have the X member function definition implement the logic, referring to p_impl_-> things all over the place, or
return p_impl->same_fn(all_the_args); and keep the logic inside the Impl class?
If you choose 1. then you end up with a function declaration in the header, and a (slightly messier than usual) definition in the matching implementation file.
If you choose 2. then you end up with a function declaration in the header file, a wrapping/forwarding definition in the matching implementation file, and at a minimum a definition in the Impl structure (I tend not to define the functions outside the Impl class definition - it's an implementation detail and the interface is not public anyway).
There is no generally desirable way to improve on this situation (i.e. macro hackery and extra code-generation scripts in your build process may occasionally be warranted, but very rarely).
It may not matter a whole heap, though it may be of interest that a variation on the second approach is to first implement a class that doesn't use the pimpl idiom (complete with proper header and optionally inline functions), you can then wrap it with a pimpl management object and forward functions to it, and in that way you keep the freedom to have some code somewhere some day decide it wants to use the functionality without using the pimpl wrapper, perhaps for improved performance / reduced memory usage at the cost of the recompilation dependency. You can also do this to make use of a specific instantiation of a template without exposing the template's code.
To illustrate this option (as requested in a comment), let's start with a silly non-pimpl class X in its own files, then create a Pimpl::X wrapper (the use of namespace and the same class name is entirely optional but facilitates flipping client code to use either, and a reminder - this isn't meant to be concise, the point here is to let a non-pImpl version be usable too):
// x.h
class X
{
public:
int get() const { return n_; } // inline
void operator=(int); // out-of-line definition
private:
int n_;
};
// x.c++
#include <x.h>
void X::operator=(int n) { n_ = n * 2; }
// x_pimpl.h
namespace Pimpl
{
class X
{
public:
X();
X(const X&);
~X();
X& operator=(const X&);
int get() const;
void operator=(int);
private:
struct Impl;
Impl* p_impl_;
};
}
x_pimpl.c++
#include <x.h>
namespace Pimpl
{
struct X::Impl
{
::X x_;
};
// the usual handling...
X() : p_impl_(new Impl) { }
X(const X& rhs) : p_impl(new Impl) { p_impl_->x_ = rhs.p_impl_->x_; }
~X() { delete p_impl_; }
X& operator=(const X& rhs) { p_impl_->x_ = rhs.p_impl_->x_; return *this; }
// the wrapping...
int X::get() const { return p_impl_->x_.get(); }
void X::operator=(int n) { p_impl_->x_ = n; }
}
If you opt for the above variation on 2, which makes the "implementation" a usable entity in it's own right, then yes - you may end up with 2 declarations and 2 definitions related to a single function, but then one of the definitions will be a simple wrapper/forwarding function which is only significantly repetitive and tedious if the functions are very short and numerous but have lots of parameters.
There's no requirement to treat the IMPL object to the same rules & standards as an object declaration in the .h file. By allowing member variables to be public (via a struct declaration), you don't need to implement an unnecessary wrapper layer. This is generally safe, since only the .cpp file has access to IMPL anyway.
Consider the following code that achieves the benefits of the PIMPL idiom without unnecessary code duplication:
// x.h
class X {
public:
X();
~X();
X(const X&) = delete;
X& operator =(const X&) = delete;
void set(int val);
int get() const;
private:
struct IMPL;
IMPL* impl;
};
// x.cpp
#include "x.h"
struct X::IMPL {
int val;
};
X::X() : impl(new IMPL) {}
X::~X() { delete impl; }
void X::set(int val)
{
impl->val = val;
}
int X::get() const
{
return impl->val;
}
// main.cpp
#include <iostream>
#include "x.h"
int main (int, char *[])
{
X x;
x.set(10);
std::cout << x.get() << std::endl;
return 0;
}
I'm just going to start by sumarizing to make sure I understand: You like the benefits of using pimpl, but dislike the amount of boilerplate code when adding or modifying functions?
In a nutshell, there is no template magic you can use to eliminate this boilerplate, but there are things to consider here as well:
You write code only once but read it many times, and you have at your disposal a variety of copy-paste capabilities. Initially creating the function isn't the majority of the time you will spend on this class. Compiling and maintaining is where your time will be spent.
Be sure to keep the public class API as simple as possible. The fewer functions you have in the public API the less boilerplate you have to write. You can make as many functions as you like in the impl and y ou only have to modify them there.
If you find yourself changing the public class API many many times, you might wish to slightly adjust your design process. Spend ten more minutes up front looking at/writing down use cases and you may reduce your API changes by 90%.

Template meta-programming with member function pointers?

Is it possible to use member function pointers with template meta-programming? Such as:
class Connection{
public:
string getName() const;
string getAlias() const;
//more stuff
};
typedef string (Connection::*Con_Func)() const;
template<Con_Func _Name>
class Foo{
Connection m_Connect;
public:
Foo(){
cout << (m_Connect.*_Name)();
}
};
typedef Foo<&Connection::getName> NamedFoo;
typedef Foo<&Connection::getAlias> AliasFoo;
Granted, this is rather contrived but is it possible? (yes, there are probably much better ways but humor me.)
Check out this discussion on the subject of pointers-to-nonstatic-members as template parameters. It looks like there are issues with the VC++ implementation.
If you are asking, can pointers to members be used as template parameters, then yes they can. There are a number of errors in your code though. This is, I think, what you might mean:
// Necessary includes
#include <string>
#include <iostream>
#include <ostream>
class Connection{
public:
// Use std:: for standard string class
std::string getName() const;
std::string getAlias() const;
//more stuff
};
typedef std::string (Connection::*Con_Func)() const;
template<Con_Func _Name>
class Foo{
Connection m_Connect;
public:
// Constructors don't have return values
Foo(){
// Correct syntax for function call through pointer to member
std::cout << (m_Connect.*_Name)();
}
};
typedef Foo<&Connection::getName> NamedFoo;
typedef Foo<&Connection::getAlias> AliasFoo;