I want to use a datatype with a different name (create a duplicate of a type).
I don't want to use 'typedef' since that only creates a #define/macro like an alias.
#include <iostream>
typedef int AnInt;
struct Number
{
int a;
};
template<typename T>
T var;
int main()
{
var<int> = 5;
var<AnInt> = 7; // does not what i want (this changes var<int>)
var<Number>.a = 7;
return 0;
}
This works exactly how I want it to work but I always need to access the type with the postfix .a.
Is there a way to avoid this?
Edit:
The real-world application is that I have a vec3 datatype and now I need to different datatypes Position and Velocity that are essentially a single vec3. They need to be different because I use an entity-component system that is based on templates.
The simplest way to create a new, non-implicitly-convertible type with exactly the same layout as the original is inheritance:
struct Position: vec3 {};
struct Velocity: vec3 {};
Note that they're still implicitly convertible to vec3d&, just not to each other.
Since typedef simply creates an alias (not a macro though) for the type, you need to create a new type to represent its new identity. Since you want the access to the value to be as smooth as possible, you can define a new class and overload some operators:
template <class T>
class wrapper
{
T value;
public:
wrapper()
{
}
wrapper(T &&obj) : value(std::move(obj))
{
}
wrapper(const T &obj) : value(obj)
{
}
operator T&()
{
return value;
}
operator const T&() const
{
return value;
}
T &operator*()
{
return value;
}
const T &operator*() const
{
return value;
}
const T &operator->() const
{
return value;
}
T &operator->()
{
return value;
}
};
Add more operators, if necessary. Then, each new type shall inherit from this class like this:
struct new_int : public wrapper<int>
{
new_int()
{
}
new_int(int &&obj) : wrapper<int>(std::move(obj))
{
}
new_int(const int &obj) : wrapper<int>(obj)
{
}
};
You can create a macro that helps with constructing these types:
#define new_type(name, base) struct name : public wrapper<base> { \
name() {} \
name(base &&obj) : wrapper<base>(std::move(obj)) {} \
name(const base &obj) : wrapper<base>(obj) {} \
}
All these new types will be distinct from each other:
new_type(new_int1, int);
new_type(new_int2, int);
int main()
{
var<int> = 12;
var<wrapper<int>> = 13;
var<new_int1> = 14;
var<new_int2> = 15;
std::cout << var<int> << std::endl;
std::cout << var<wrapper<int>> << std::endl;
std::cout << var<new_int1> << std::endl;
std::cout << var<new_int2> << std::endl;
}
If you want to ensure type safety try foonathan/type_safe. This is a header-only library that provides mechanisms for opaque typedef emulation using standard C++:
type_safe provides zero overhead abstractions that use the C++ type
system to prevent bugs.
Zero overhead abstractions here and in following mean abstractions that have no cost with optimizations enabled, but may lead to slightly
lower runtime in debug mode, especially when assertions for this
library are enabled.
The library features cannot really explained in the scope of this
readme, I highly suggest that you check out the first and second blog
post and the examples.
If you only need to use strong typedefs for something that involves physics, have a look at Boost.Units:
The Boost.Units library is a C++ implementation of dimensional
analysis in a general and extensible manner, treating it as a generic
compile-time metaprogramming problem. With appropriate compiler
optimization, no runtime execution cost is introduced, facilitating
the use of this library to provide dimension checking in
performance-critical code. Support for units and quantities (defined
as a unit and associated value) for arbitrary unit system models and
arbitrary value types is provided, as is a fine-grained general
facility for unit conversions. Complete SI and CGS unit systems are
provided, along with systems for angles measured in degrees, radians,
gradians, and revolutions and systems for temperatures measured in
Kelvin, degrees Celsius and degrees Fahrenheit. The library
architecture has been designed with flexibility and extensibility in
mind; demonstrations of the ease of adding new units and unit
conversions are provided in the examples.
P.S. If you would like some code examples then let me know.
Related
Having returned relatively recently to C++ after decades of Java, I am currently struggling with a template-based approach to data conversion for instances where type erasure has been applied. Please bear with me, my nomenclature may still be off for C++-natives.
This is what I am trying to achieve:
Implement dynamic variables which are able to hold essentially any value type
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to hold variable instances in containers, independent of their value type
Convert between variable value and representation using conversion functions
Be able to introduce new representations just by providing new conversion functions
Constraints: use only C++-11 features if possible, no use of libraries like boost::any etc.
A rough sketch of this might look like this:
#include <iostream>
#include <vector>
void convert(const std::string &f, std::string &t) { t = f; }
void convert(const int &f, std::string &t) { t = std::to_string(f); }
void convert(const std::string &f, int &t) { t = std::stoi(f); }
void convert(const int &f, int &t) { t = f; }
struct Variable {
virtual void get(int &i) = 0;
virtual void get(std::string &s) = 0;
};
template <typename T> struct VariableImpl : Variable {
T value;
VariableImpl(const T &v) : value{v} {};
void get(int &i) { convert(value, i); };
void get(std::string &s) { convert(value, s); };
};
int main() {
VariableImpl<int> v1{42};
VariableImpl<std::string> v2{"1234"};
std::vector<Variable *> vars{&v1, &v2};
for (auto &v : vars) {
int i;
v->get(i);
std::string s;
v->get(s);
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
return 0;
}
The code does what it is supposed to do, but obvoiusly I would like to get rid of Variable::get(int/std::string/...) and instead template them, because otherwise every new representation requires a definition and an implementation with the latter being exactly the same as all the others.
I've played with various approaches so far, like virtual templated, methods, applying the CRDT with intermediate type, various forms of wrappers, yet in all of them I get bitten by the erased value type of VariableImpl. On one hand, I think there might not be a solution, because after type erasure, the compiler cannot possibly know what templated getters and converter calls it must generate. On the other hand I think i might be missing something really essential here and there should be a solution despite the constraints mentioned above.
This is a classical double dispatch problem. The usual solution to this problem is to have some kind of dispatcher class with multiple implementations of the function you want to dispatch (get in your case). This is called the visitor pattern. The well-known drawback of it is the dependency cycle it creates (each class in the hierarchy depends on all other classes in the hierarchy). Thus there's a need to revisit it each time a new type is added. No amount of template wizardry eliminates it.
You don't have a specialised Visitor class, your Variable serves as a Visitor of itself, but this is a minor detail.
Since you don't like this solution, there is another one. It uses a registry of functions populated at run time and keyed on type identification of their arguments. This is sometimes called "Acyclic Visitor".
Here's a half-baked C++11-friendly implementation for your case.
#include <map>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <functional>
#include <string>
#include <stdexcept>
struct Variable
{
virtual void convertValue(Variable& to) const = 0;
virtual ~Variable() {};
virtual std::type_index getTypeIdx() const = 0;
template <typename K> K get() const;
static std::map<std::pair<std::type_index, std::type_index>,
std::function<void(const Variable&, Variable&)>>
conversionMap;
template <typename T, typename K>
static void registerConversion(K (*fn)(const T&));
};
template <typename T>
struct VariableImpl : Variable
{
T value;
VariableImpl(const T &v) : value{v} {};
VariableImpl() : value{} {}; // this is needed for a declaration of
// `VariableImpl<K> below
// It can be avoided but it is
// a story for another day
void convertValue(Variable& to) const override
{
auto typeIdxFrom = getTypeIdx();
auto typeIdxTo = to.getTypeIdx();
if (typeIdxFrom == typeIdxTo) // no conversion needed
{
dynamic_cast<VariableImpl<T>&>(to).value = value;
}
else
{
auto fcnIter = conversionMap.find({getTypeIdx(), to.getTypeIdx()});
if (fcnIter != conversionMap.end())
{
fcnIter->second(*this, to);
}
else
throw std::logic_error("no conversion");
}
}
std::type_index getTypeIdx() const override
{
return std::type_index(typeid(T));
}
};
template <typename K> K Variable::get() const
{
VariableImpl<K> vk;
convertValue(vk);
return vk.value;
}
template <typename T, typename K>
void Variable::registerConversion(K (*fn)(const T&))
{
// add a mutex if you ever spread this over multiple threads
conversionMap[{std::type_index(typeid(T)), std::type_index(typeid(K))}] =
[fn](const Variable& from, Variable& to) {
dynamic_cast<VariableImpl<K>&>(to).value =
fn(dynamic_cast<const VariableImpl<T>&>(from).value);
};
}
Now of course you need to call registerConversion e.g. at the beginning of main and pass it each conversion function.
Variable::registerConversion(int_to_string);
Variable::registerConversion(string_to_int);
This is not ideal, but hardly anything is ever ideal.
Having said all that, I would recommend you revisit your design. Do you really need all these conversions? Why not pick one representation and stick with it?
Implement dynamic variables which are able to hold essentially any value type
Be able to hold variable instances in containers, independent of their value type
These two requirements are quite challenging on its own. The class templates don't really encourage inheritance, and you already did the right thing to hold what you asked for: introduced a common base class for the class template, which you can later refer to in order to store pointers of the said type in a collection.
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to introduce new representations just by providing new conversion functions
This is where it breaks. Function templates assume common implementation for different types, while inheritance assumes different implementation for the same types.
You goal is to introduce different implementation for different types, and in order to make your requirements viable you have to switch to one of those two options instead (or put up with a number of functions for each case which you have already introduced yourself)
Edit:
One of the strategies you may employ to enforce inheritance approach is generalisation of the arguments to the extent where they can be used interchangeably by the abstract interface. E.g. you may wrap the converting arguments inside of a union like this:
struct Variable {
struct converter_type {
enum { INT, STRING } type;
union {
int* m_int;
std::string* m_string;
};
};
virtual void get(converter_type& var) = 0;
virtual ~Variable() = default;
};
And then take whatever part of it inside of the implementation:
void get(converter_type& var) override {
switch (var.type) {
case converter_type::INT:
convert(value, var.m_int);
break;
case converter_type::STRING:
convert(value, var.m_string);
break;
}
}
To be honest I don't think this is a less verbose approach compared to just having a number of functions for each type combination, but i think you got the idea that you can just wrap your arguments somehow to cement the abstract class interface.
Implement std::any. It is similar to boost::any.
Create a conversion dispatcher based off typeids. Store your any alongside the conversion dispatcher.
"new conversion functions" have to be passed to the dispatcher.
When asked to convert to a type, pass that typeid to the dispatcher.
So we start with these 3 types:
using any = std::any; // implement this
using converter = std::function<any(any const&)>;
using convert_table = std::map<std::type_index, converter>;
using convert_lookup = convert_table(*)();
template<class T>
convert_table& lookup_convert_table() {
static convert_table t;
return t;
}
struct converter_any: any {
template<class T,
typename std::enable_if<
!std::is_same<typename std::decay<T>::type, converter_any>::value, bool
>::type = true
>
converter_any( T&& t ):
any(std::forward<T>(t)),
table(&lookup_convert_table<typename std::decay<T>::type>())
{}
converter_any(converter_any const&)=default;
converter_any(converter_any &&)=default;
converter_any& operator=(converter_any const&)=default;
converter_any& operator=(converter_any&&)=default;
~converter_any()=default;
converter_any()=default;
convert_table const* table = nullptr;
template<class U>
U convert_to() const {
if (!table)
throw 1; // make a better exception than int
auto it = table->find(typeid(U));
if (it == table->end())
throw 2; // make a better exception than int
any const& self = *this;
return any_cast<U>((it->second)(self));
}
};
template<class Dest, class Src>
bool add_converter_to_table( Dest(*f)(Src const&) ) {
lookup_convert_table<Src>()[typeid(Dest)] = [f](any const& s)->any {
Src src = std::any_cast<Src>(s);
auto r = f(src);
return r;
};
return true;
}
now your code looks like:
const bool bStringRegistered =
add_converter_to_table(+[](std::string const& f)->std::string{ return f; })
&& add_converter_to_table(+[](std::string const& f)->int{ return std::stoi(f); });
const bool bIntRegistered =
add_converter_to_table(+[](int const& i)->int{ return i; })
&& add_converter_to_table(+[](int const& i)->std::string{ return std::to_string(i); });
int main() {
converter_any v1{42};
converter_any v2{std::string("1234")};
std::vector<converter_any> vars{v1, v2}; // copies!
for (auto &v : vars) {
int i = v.convert_to<int>();
std::string s = v.convert_to<std::string>();
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
}
live example.
...
Ok, what did I do?
I used any to be a smart void* that can store anything. Rewriting this is a bad idea, use someone else's implementation.
Then, I augmented it with a manually written virtual function table. Which table I add is determined by the constructor of my converter_any; here, I know the type stored, so I can store the right table.
Typically when using this technique, I'd know what functions are in there. For your implementation we do not; so the table is a map from the type id of the destination, to a conversion function.
The conversion function takes anys and returns anys -- again, don't repeat this work. And now it has a fixed signature.
To add support for a type, you independently register conversion functions. Here, my conversion function registration helper deduces the from type (to determine which table to register it in) and the destination type (to determine which entry in the table), and then automatically writes the any boxing/unboxing code for you.
...
At a higher level, what I'm doing is writing my own type erasure and object model. C++ has enough power that you can write your own object models, and when you want features that the default object model doesn't solve, well, roll a new object model.
Second, I'm using value types. A Java programmer isn't used to value types having polymorphic behavior, but much of C++ works much better if you write your code using value types.
So my converter_any is a polymorphic value type. You can store copies of them in vectors etc, and it just works.
I have a function that takes a T and calls specific functions on the supplied object. Until now it was used from compile-time objects, so all was great. Minimal example:
#include <iostream>
struct A {
void fun() const { std::cout << "A" << std::endl; }
};
struct B {
void fun() const { std::cout << "B" << std::endl; }
};
template<class T>
void use_function(const T& param) {
param.fun();
}
int main() {
use_function(A{}); // "A"
use_function(B{}); // "B"
return 0;
}
Now I'm trying to use that use_function() with objects that get created at runtime and having a hard time. I can't use std::variant or std::any since I need to supply the type as template parameter for their access functions - although all their variants fulfil the function interface. Example for a (failing) variant approach:
using var_type = std::variant<A, B>;
struct IdentityVisitor {
template<class T>
auto operator()(const T& alternative) const -> T {
return alternative;
}
};
int main() {
var_type var = A{};
// error C2338: visit() requires the result of all potential invocations to have the same type and value category (N4828 [variant.visit]/2).
use_function(std::visit(IdentityVisitor{}, var));
return 0;
}
What is possible is directly calling the function with an appropriate type like this:
if (rand() % 2 == 0)
use_function(A{});
else
use_function(B{});
just storing it in between is what I can't get working.
I understand on a technical level but having trouble coming up with an elegant solution. Is there one? I know that I could rewrite the objects with even a lightweight inheritance - but was trying to see if it's feasible to avoid it altogether, even if just as an exercise to avoid OOP in favor of templates and concepts. I feel like variants should be working with this, but apparently not.
std::visit([](auto const& x) { use_function(x); }, var);
If overload sets were objects, you could pass use_function to std::visit directly. Because they aren't, you need to wrap it in something that will be instantiated as a call to the right overload.
std::visit([](auto const& x) { use_function(x); }, var);
Are we supposed to be able to inherit from Qt containers such as QList, QVector or QMap in order to specialize them and add functionality? If so, what do we need to do in order to be sure that the container works correctly (virtual methods, virtual destructor etc..?). If not, why not and what other options do I have?
Both, STL and Qt Containers opt for non virtual destructors.
There is an interesting discussion why this is, and why its not fixed with Qt5.
QList has no virtual destructor, but is inherited from http://qt-project.org/forums/viewthread/16416
Also, note further differences between STL style and Qt containers. Quoting Jens Weller in his Blog post An introduction into Qt:
Still, there is an important difference between Qt containers and STL containers: Qt containers have value semantics, and will only perform copy on write, while a std container will copy its full contents when copied. This behavoir accounts for most of Qt base classes, that they will only create a new instance for data, when needed. This implicit sharing of resources is a very important concept to understand when dealing with Qt and its containers.
Your options are as always:
composition
E.g.
struct MyFancyList
{
QList<MyType> _data;
bool frobnicate() { return true; }
};
free functions
E.g. extend QList with non-member operations:
template <typename> bool frobnicate(QList<T>& list)
{
// your algorithm
return true;
}
If you really wanted to do funcky stuff, like create an implicit conversion or overload a member operator, you could resort to expression templates.
Update: the latter is also the approach taken by QStringBuilder in new versions. See
Lecture: Expression Templates (video, slides) by Volker Krause
Bonus
For fun, here's a (bad!) illustration of how you could use expression templates to extend the interface of std::stack<T>. See it Live on Coliru or ideone
As we all know, std::stack doesn't model a sequential container, and therefore doesn't have begin(), end(), or operator[] defined. With a bit of hackery, we can define a eDSL to provide these features, without composition or inheritance.
To really drive the point home that you can 'overload' behaviour of the wrapped class in essential ways, we'll make it so that you can implicitly convert the result of extend(stack)[n] to a std::string, even if the stack contains e.g. int.
#include <string>
#include <stack>
#include <stdexcept>
namespace exprtemplates
{
template <typename T> struct stack_indexer_expr
{
typedef std::stack<T> S;
S& s;
std::size_t n;
stack_indexer_expr(S& s, std::size_t n) : s(s), n(n) {}
operator T() const {
auto i = s.size()-n; // reverse index
for (auto clone = s; !clone.empty(); clone.pop())
if (0 == --i) return clone.top();
throw std::range_error("index out of bounds in stack_indexer_expr");
}
operator std::string() const {
// TODO use `boost::lexical_cast` to allow wider range of T
return std::to_string(this->operator T());
}
};
template <typename T> struct stack_expr
{
typedef std::stack<T> S;
S& s;
stack_expr(S& s) : s(s) {}
stack_indexer_expr<T> operator[](std::size_t n) const {
return { s, n };
}
};
}
Now all we have to do is seed our expression templates. We'll use a helper function that wraps any std::stack:
template <typename T>
exprtemplates::stack_expr<T> extend(std::stack<T>& s) { return { s }; }
Ideally, our users never realize the exact types inside exprtemplates namespace:
#include <iostream>
int main()
{
std::stack<double> s;
s.push(0.5);
s.push(0.6);
s.push(0.7);
s.push(0.8);
std::string demo = extend(s)[3];
std::cout << demo << "\n";
}
Voila. More craziness:
auto magic = extend(s);
std::cout << magic[0] << "\n";
std::cout << magic[1] << "\n";
std::cout << magic[2] << "\n";
std::cout << magic[3] << "\n";
double as_double = magic[0];
std::string as_string = magic[0];
Prints
0.5
0.6
0.7
0.8
DISCLAIMERS
I know std::stack has a restrictive interface for a reason.
I know that my indexing implementation has horrific efficiency.
I know that implicit conversions are evil. This is just a contrived example.
In real life, use Boost::Proto to get a DSL going. There are many pitfalls and gotchas in doing all the mechanics by hand.
Look at QStringBuilder for a more real life sample.
In Visual Studio, there is __declspec(property) which creates properties similar to C#. Borland C++ offers the __property keyword with the exact same functionality. In the C++0x, there is mention of a implicit keyword that could be expanded to implement the same functionality. But it didn't make it into the spec.
I am looking for a portable and relatively clean method of declaring syntactically sugared properties that will compile in the latest compilers for Windows, OSX and Linux. I am not concerned with compiler compatibility, just one compiler per platform.
I am not looking for alternatives to properties that require parenthesis to get or set the property, such as overloaded methods separating the getters and setters.
Here is an ideal usage which compiles in Visual Studio 2010:
#define _property(_type, _name, _get, _put) __declspec(property(get=_get, put=_put)) _type _name
#define _property_readonly(_type, _name, _get) __declspec(property(get=_get)) _type _name
class Window
{
public:
_property_readonly(void*, Handle, GetHandle);
_property(bool, Visible, GetVisible, SetVisible);
void* GetHandle();
bool GetVisible();
void SetVisible(bool);
}
void main()
{
Window MainWindow;
if (!MainWindow.Visible)
MainWindow.Visible = true;
}
This is something similar to what you are asking and is (I hope) standard C++...
#include <iostream>
template<typename C, typename T, T (C::*getter)(), void (C::*setter)(const T&)>
struct Property
{
C *instance;
Property(C *instance)
: instance(instance)
{
}
operator T () const
{
return (instance->*getter)();
}
Property& operator=(const T& value)
{
(instance->*setter)(value);
return *this;
}
template<typename C2, typename T2,
T2 (C2::*getter2)(), void (C2::*setter2)(const T2&)>
Property& operator=(const Property<C2, T2, getter2, setter2>& other)
{
return *this = (other.instance->*getter2)();
}
Property& operator=(const Property& other)
{
return *this = (other.instance->*getter)();
}
};
//////////////////////////////////////////////////////////////////////////
struct Foo
{
int x_, y_;
void setX(const int& x) { x_ = x; std::cout << "x new value is " << x << "\n"; }
int getX() { std::cout << "reading x_\n"; return x_; }
void setY(const int& y) { y_ = y; std::cout << "y new value is " << y << "\n"; }
int getY() { std::cout << "reading y_\n"; return y_; }
Property<Foo, int, &Foo::getX, &Foo::setX> x;
Property<Foo, int, &Foo::getY, &Foo::setY> y;
Foo(int x0, int y0)
: x_(x0), y_(y0), x(this), y(this)
{
}
};
int square(int x)
{
return x*x;
}
int main(int argc, const char *argv[])
{
Foo foo(10, 20);
Foo foo2(100, 200);
int x = foo.x; std::cout << x << "\n";
int y = foo.y; std::cout << y << "\n";
foo.x = 42; std::cout << "assigned!\n";
x = foo.x; std::cout << x << "\n";
std::cout << "same instance prop/prop assign!\n";
foo.x = foo.y;
std::cout << "different instances prop/prop assign\n";
foo.x = foo2.x;
std::cout << "calling a function accepting an int parameter\n";
std::cout << "square(" << foo.x << ") = " << square(foo.x) << "\n";
return 0;
}
As you can see from main the usage is transparent as long as you are assigning values of type T (here int) or implicitly convertible to T to properties and as long you are converting them back to T values on reading.
Behavior will be different however if you for example pass foo.x to a template function because the type of foo.x is not int but Property<Foo, int, ...> instead.
You can also have problems with non-template functions... calling a function accepting a T value will work fine, however a T& parameter is for example going to be a problem because basically the function is asking a variable to access directly using the address. For the same reason you cannot pass of course the address of a property to a function accepting a T* parameter.
Clang now has the Microsoft __declspec(property...) fully implemented and it optimizes beautifully. So you can use properties in your c++ across all platforms and intermix in gcc based or c99 code etc.
I have been using it for over a year, and waited for this to appear universally for more than five years.
It is one of the most powerful C++ tools for abstracting structure and refactoring code. I use it all the time to allow me to quickly build a structure and then refactor it later as performance or restructuring requires it.
It is invaluable and I really don't understand why the C++ standards have not adopted it long ago. But then again, they have so much of the complex and bloated boost way of using c++ and templates.
Clang is so portable across every platform now that having this feature is fantastic.
Development within (free or paid version of) Visual Studio using clang is almost seamless and you get the incredible debugging development toolset that just makes working on other toolsets and platforms painful by comparison.
I exclusively use clang now for all my c++ development.
See also: this cross-reference post
I am looking for a portable and
relatively clean method of declaring
syntactically sugared properties that
will compile in the latest compilers
for Windows, OSX and Linux.
You're describing "meta-object" type capabilities, like compile-time or run-time defined properties, such as those that may be otherwise implemented through "Java beans" or ".NET reflection", or any number of ways with high-level scripting languages, like Python and Perl.
For example, what you're describing (compile-time and/or run-time properties) is implemented in the Qt (C++) libraries through the QMetaObject. You can instantiate it directly, use it as a "member" in your classes, or derive from QObject to "automatically" get that meta-object behavior (and some other things, like "casting" helps, and signals/slots cross-threads). Of course, these are quite cross-platform (e.g., Win, Mac, Posix).
I'm not a big fan of the __declspec() usage, except for very platform-specific use, such as explicit exporting of types through a "Microsoft Extension DLL" (which I generally try to avoid if possible). I don't think there's any way to make such usage "cross-platform" (since that particular usage is specific to MS DLLs).
Similarly, it wouldn't be very difficult to write your own "MyMetaObject" type class that is essentially a "dictionary" or "hash" or "associative array", which your objects use, and which is populated dynamically at runtime, even with your internal types (such as MyColor, MyTime, MyFilePath, etc.) I've done that several times, and it need not be lots of work, and it can work quite elegantly. (The QMetaObject is typically quite a bit more powerful than these simple approaches, but it requires the "moc" compilation step, which is a very powerful step to generate fast lookup code for its properties, and to enable signals/slots).
Finally, you're starting to touch lightly into the "Dynamic C++" domain, which implies lighter, almost script-like usage of C++ syntax. Here's one proposal that goes into a bit of depth about this dynamic usage, where you script with these properties, not needing to re-compile. (This particular proposal happens to be based on the QMetaObject type behavior, but there are other proposals with similar usage thoughts):
http://www.codeproject.com/KB/cpp/dynamic_cpp.aspx
If you google "Dynamic C++" or "C++ Scripting", you might get some more ideas. There's some wickedly clever thoughts in some of that stuff.
I like the answer of 6502. It uses both less memory and is faster than the solution i will present. Only mine will have a bit syntactic sugar.
I wanted to be able to wite something like this (with PIMPL idiom):
class A {
private:
class FImpl;
FImpl* Impl;
public:
A();
~A();
Property<int> Count;
Property<int> Count2;
Property<UnicodeString> Str;
Property<UnicodeString> Readonly;
};
Here comes the completet code (I am quite sure it is standard conformant):
template <typename value_t>
class IProperty_Forward {
public:
virtual ~IProperty_Forward() {}
virtual const value_t& Read() = 0;
virtual void Set(const value_t& value) = 0;
};
template <typename value_t, typename owner_t, typename getter_t, typename setter_t>
class TProperty_Forwarder: public IProperty_Forward<value_t>
{
private:
owner_t* Owner;
getter_t Getter;
setter_t Setter;
public:
TProperty_Forwarder(owner_t* owner, getter_t& getter, setter_t& setter)
:Owner(owner), Getter(getter), Setter(setter)
{ }
const value_t& Read()
{ return (Owner->*Getter)(); }
void Set(const value_t& value)
{ (Owner->*Setter)(value); }
};
template <typename value_t>
class Property {
private:
IProperty_Forward<value_t>* forward;
public:
Property():forward(NULL) { }
template <typename owner_t, typename getter_t, typename setter_t>
Property(owner_t* owner, getter_t getter, setter_t setter)
{ Init(owner, getter, setter); }
~Property()
{ delete forward; }
template <typename owner_t, typename getter_t, typename setter_t>
void Init(owner_t* owner, getter_t getter, setter_t setter)
{
forward = new TProperty_Forwarder<value_t, owner_t, getter_t, setter_t>(owner, getter, setter);
}
Property& operator=(const value_t& value)
{
forward->Set(value);
return *this;
}
const value_t* operator->()
{ return &forward->Read(); }
const value_t& operator()()
{ return forward->Read(); }
const value_t& operator()(const value_t& value)
{
forward->Set(value);
return forward->Read();
}
operator const value_t&()
{ return forward->Read(); }
};
And some implementation details:
class A::FImpl {
public:
FImpl():FCount(0),FCount2(0),FReadonly("Hello") { }
UnicodeString FReadonly;
const UnicodeString& getReadonly()
{ return FReadonly; }
void setReadonly(const UnicodeString& s)
{ }
int FCount;
int getCount()
{ return FCount; }
void setCount(int s)
{ FCount = s; }
int FCount2;
int getCount2()
{ return FCount2; }
void setCount2(int s)
{ FCount2 = s; }
UnicodeString FStr;
const UnicodeString& getStr()
{ return FStr; }
void setStr(const UnicodeString& s)
{ FStr = s; }
};
A::A():Impl(new FImpl)
{
Count.Init(Impl, &FImpl::getCount, &FImpl::setCount);
Count2.Init(Impl, &FImpl::getCount2, &FImpl::setCount2);
Str.Init(Impl, &FImpl::getStr, &FImpl::setStr);
Readonly.Init(Impl, &FImpl::getReadonly, &FImpl::setReadonly);
}
A::~A()
{
delete Impl;
}
I am using C++ Builder for anyone who wonders about the UnicodeString class.
Hope it helps others for experimentation of Standard conforming c++ Properties.
The basic mechanism is the same as 6502, with the same limitations.
I would like my classes to be identified each type by an unique hash code. But I don't want these hashed to be generated every time a method, eg. int GetHashCode(), is invoked during runtime. I'd like to use already generated constants and I was hoping there is a way to make the compiler do some come computing and set these constants. Can it be done using templates? Could you give me some example, if it is possible.
UPDATE:
Thanks to kriss' comment I realized my question should go like this:
How to do the type checking with the lowest runtime cost possible?
I'd like to check a pointer to an object against a class type. Just the classes I implement in my libs, so I was thinking of some custom hashing, thus the original question. I did consider using typeid but I am unaware of the runtime cost of using it. I made an assumption that since typeid produces a type_info class that would be more consuming than simple comparision of unique int values.
You can do it with boost.MPL.
I would go simple route:
For classes that would be static property - so just pick a number for each class.
For instances - just use the address.
Static const's are evaluated at compile time - which is pretty much the basis for metaprogramming at large. Moreover, type_info::hash_code is particularly adapted for your needs, so try -
class MyClass
{
static const size_t TypeHashCode = typeid(MyClass).hash_code();
...
}
(I'm not around a compiler right now, so this may take some refining. Will try and recheck tomorrow)
EDIT: indeed, it is not only MS specific but also added only in VS2010 - but hey, at least MS agrees this is a valid need. If you don't allow both VS2010 and boost in your code - you're pretty much left with the standard compliant facilities: typeid or dynamic_cast. They do incur some overhead, but I'd take extra care to verify this overhead is indeed a worthy battle. (my money goes to - not.)
All such classes share something common. Then why not add a symbolic constant in a common enum for each one, you'll leave the enum give values for you, it's easier than giving explicit constants (you still have to declare each class in the enum).
template<class T>
struct provide_hash_code_for_class
{
public:
static uintptr_t GetHashCode()
{
return(reinterpret_cast<uintptr_t>(&unused));
}
private:
static void *unused;
};
template<class T>
void *provide_hash_code_for_class<T>::unused;
class MyClass : public provide_hash_code_for_class<MyClass>
{
};
int main()
{
std::cout << std::hex << MyClass::GetHashCode() << std::endl;
std::cout << std::hex << MyClass().GetHashCode() << std::endl;
return(0);
}
Please be aware that hash codes will change between runs so you can't rely on them for example for interprocess communication.
building on the simple route route by Nikolai N Fetissov:
For classes that would be static property - use the address of a function cast to an intptr_t to give a unique yet compiled-in value.
For instances - just use the address.
It is a pitty that there is no compile-time type hash_code supported by the standard. As a workaround, one can generate a compile time hash from the class name. An example below.
#include <stdint.h>
#include <string>
#include <vector>
#include <iostream>
#include <memory>
#include <cassert>
//Compile-time string hashing.
class HashedString
{
public:
typedef int64_t HashType;
explicit constexpr HashedString(const char* str): m_hash(hashString(str)) {}
static inline constexpr HashType hashString(const char* str)
{
return ( !str ? 0 : hashStringRecursive(5381, str));
}
static inline constexpr HashType hashStringRecursive(HashType hash, const char* str)
{
return ( !*str ? hash : hashStringRecursive(((hash << 5) + hash) + *str, str + 1));
}
const HashType m_hash;
};
struct EventBase
{
using IdType = HashedString::HashType;
virtual ~EventBase() {}
IdType getId() const { return m_eventId; } //present the runtime event id
EventBase(IdType myId) : m_eventId { myId } { }
template<class DerivedEvent>
const DerivedEvent* getAs() const
{
return dynamic_cast<const DerivedEvent*>(this);
}
protected:
const IdType m_eventId;
};
#define DEFINE_EVENT_ID(className) \
static constexpr IdType id = HashedString(#className).m_hash; \
struct SomeEvent1 : public EventBase
{
DEFINE_EVENT_ID(SomeEvent1);
SomeEvent1(int status) : EventBase(id), m_status { status } { assert(id == m_eventId); }
int m_status;
};
struct SomeEvent2 : public EventBase
{
DEFINE_EVENT_ID(SomeEvent2);
SomeEvent2() : EventBase(id) { assert(id == m_eventId); }
std::string m_s = "test event 2";
};
void testEvents()
{
std::vector<std::shared_ptr<EventBase>> events;
events.push_back(std::make_shared<SomeEvent1>(123));
events.push_back(std::make_shared<SomeEvent2>());
for (auto event : events) {
switch(event->getId()) {
case SomeEvent1::id:
std::cout << "SomeEvent1 " << event->getAs<SomeEvent1>()->m_status << std::endl;
break;
case SomeEvent2::id:
std::cout << "SomeEvent2 " << event->getAs<SomeEvent2>()->m_s << std::endl;
break;
}
}
}