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.
Related
I am working on incorporating a new implementation based on an older, fixed API and moving in somewhat contradicting terrain because I need to pair a templated pure interface with runtime-dependent usage. While doing so I want to be as lazy as possible and reduce boilerplate code to a minimum. I've got a working version with some minor quirks and a lot of boilerplate needed. Consider the following code example.
template<typename T, typename U>
class FooLegacyApiContract {
public:
// FooLegacyApiContract must not hold any default implementation and _only_ defines an unchangeable contract
virtual void doFoo(const T &x, const U &y) = 0;
// about 20 other methods, some with T and/or U, some without.
};
class FooImpl
: public FooLegacyApiContract<int, int>, public FooLegacyApiContract<double, int>, public FooLegacyApiContract<long,long>, public FooLegacyApiContract<std::string,long> {
public:
// (1) implementation of doFoo(int, int) -> delegate to common solution, here in FooImpl. Still virtual.
virtual void doFoo(const int &x, const int &y) override {
doIntegerLikeStuff(x, y);
}
// (2) implementation of doFoo(long,long) -> delegate to common solution, here in FooImpl. Still virtual.
virtual void doFoo(const long &x, const long &y) override {
doIntegerLikeStuff(x, y);
}
// (3) implementation of doFoo(double,int) -> do special stuff, just here in FooImpl
virtual void doFoo(const double &x, const int &y) override {
std::cout << "FooImpl Doing specific stuff with a double,int=" << x << "," << y << std::endl;
}
// (4) implementation of doFoo(std::string, long) -> do special stuff, just here in FooImpl
virtual void doFoo(const std::string &x, const long &y) override {
std::cout << "FooImpl Doing specific stuff with a string,long=" << x << "," << y << std::endl;
}
private:
template<typename T, typename U>
void doIntegerLikeStuff(const T &x, const U &y) {
// TODO: maybe statically assert that T,U has a valid combination supported by this method here
std::cout << "FooImpl Doing stuff with a either <int,int> or <long, long>=" << x << "," << y << std::endl;
}
};
// Reuse FooImpl but change a method
class HalvingFirstIntFooImpl : public FooImpl {
public:
using FooImpl::doFoo; // (5) Without this the other doFoo will not be visible.
void doFoo(const int &x, const int &y) override {
std::cout << "HalvingFirstIntFooImpl Doing stuff differently with an int,int=" << x / 2 << "," << y << std::endl;
}
};
// completely different, scoped implementation of contract, allows only ints
class DoublingFirstIntImpl : public FooLegacyApiContract<int, int> {
public:
void doFoo(const int &x, const int &y) override {
std::cout << "DoublingFirstIntImpl int=" << x * 2 << std::endl;
}
};
int main() {
FooImpl fi;
HalvingFirstIntFooImpl halve_ints_fi;
DoublingFirstIntImpl doubling_ints_only;
fi.doFoo(1, 1);
fi.doFoo(2L, 2L);
fi.doFoo(3.1415, 35);
fi.doFoo("test", 42L);
// the following line does not work without (5)
halve_ints_fi.doFoo("more testing", 12345L);
FooImpl& fi_ref = halve_ints_fi;
fi_ref.doFoo(22, 22);
fi_ref.doFoo(1337L, 4711L);
fi_ref.doFoo("another test", 50L);
// Dynamic dispatch needed b/c user input chooses betwen FooImpl, HalvingFirstIntFooImpl and DoublingFirstIntImpl
FooLegacyApiContract < int, int > *ref = &fi; // (6) Why is this not working with FooLegacyApiContract<int>& ?
ref->doFoo(200, 200);
ref = &halve_ints_fi;
ref->doFoo(300, 300);
ref = &doubling_ints_only;
ref->doFoo(400, 400);,
FooLegacyApiContract < double , int > * another_ref = &fi;
another_ref = &halve_ints_fi;
// the following line does not compile, which is good!
// another_ref = &doubling_ints_only;
}
FooLegacyApiContractis the contract class I'm not allowed to change, as it's library code outside of my responsibility. It rarely changes and can be considered fixed. The version chosen here is obv. very contrived. In reality it's a repository-API with a lot of different demanded semantics. T, U are not pritive. Especially T is actually a container of T most methods of FooLegacyApiContract.
The long definition of FooImpl is fine. I guess I could reduce it with with some CRTP variadic template magic.
Ideally I want (1) and (2) to be generated by the compiler.
In a perfect world I'd speficy the exceptions to the rule of T,U-pairs for which a non-generic implementation needs to be supplied manually.
Even more perfect would be some form of wildcard for T and/or U.
Subclasses of FooImpl need to be able to change this behavior. HalvingFirstIntFooImpl is an example. Must(?) remain virtual so that dynamic dispatch works in the Impl class hierarchy.
(3) and (4) are such very specific implementations for T=long, U=long and T=string, U=long. They're valid only for FooImpl and its subclasses.
(5) is a quirk. Why do I have to put this in to gain access to non-overwritten doFoo in HalvingFirstIntFooImpl? I guess this is because of doFoo coming from a template.
Is there a short way to tell the compiler to auto-use any FooLegacyApiContract method implemented (automatically or manually) in FooImpl?
(6) is finally the use case I need to support.
At runtime, user input defines what implementation will be used by assigning a pointer, but preferribly a reference.
Using a reference here does not work due to slicing issues. I solved it with using a pointer for now, but I'd like a reference.
The type of that pointer/reference depends on the context.
Legacy code uses FooLegacyApiContract<T,U>& and I'd like to pass in instances of FooImpl.
In bundled, interdepedent implemementations of my own I'd might demand a FooImpl& or FooImpl*.
I feel like going CRTP and partial template specialization, maybe even SFINAE could be parts of a solution but a have a hard time mixing it with the requirement to not touch FooLegacyApiContract and keep its virtual-nature.
I'd be really happy if someone could point me in the right direction.
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.
The locale Facet constructor:
Constructs a copy of other except for the facet of type Facet (typically deduced from the type of the argument) which is installed from the argument facet. If facet is NULL, the constructed locale is a full copy of other. The locale constructed in this manner has no name.
I try to construct using my Facet here, but when I put a break-point in my do_decimal_point and do_thousands_sep they are never called :(
I can see the Facet being passed in, but it's passed into standard library implementation files so I can't see if anything is ever done with it.
I've tried this on Visual Studio 2013, Clang 3.6.0, and gcc 4.9.2. All of them behave as though I had never passed in a Facet just using the other locale's behavior.
I can't find any bugs against this constructor in any of the compilers. I think I'm doing this all the right way. Why can't I get locale to construct using my Facet?
EDIT:
At the request of 0x499602D2 I have added an example. It's interesting to note that the Facet does seem to be picked up but not used with get_money. I'm linking a live example of this (which necessarily useslocale("C") instead of locale("en-US")):
class Foo : public std::moneypunct<char> {
protected:
char_type do_decimal_point() const {
cout << "Hit Foo::do_decimal_point";
return ',';
}
char_type do_thousands_sep() const {
cout << "Hit Foo::do_thousands_sep";
return '.';
}
};
int main()
{
cout.imbue(locale(locale("en-US"), new Foo));
const moneypunct<char>* temp = &use_facet<std::moneypunct<char>>(cout.getloc());
cout << temp->decimal_point() << endl << temp->thousands_sep() << endl;
istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
USCurrency.imbue(cout.getloc());
long double value;
USCurrency >> get_money(value, true);
return 0;
}
This outputs:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
I would expect it to output:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
Hit Foo::do_thousands_sepHit Foo::do_decimal_point
EDIT2:
It appears that moneypunct<char> can't be inherited from as it doesn't get constructed properly, unless it is constructed internally by the locale. Which at least on Visual Studio is a problem because it determines whether to use thousands_sep by the grouping. The work around may be to completely reimplement moneypunct<char>'s functionality. I'm tinkering with that now. In the meantime I've also added a bug here: https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information
The fact is, do_decimal_place and do_thousands_place are respected by get_money. The difficulty is in the fact that the moneypunct that is being inherited from is being default constructed, so the supporting information to direct get_money to call do_decimal_place and do_thousands_place is not being set up.
Visual Studio's implementation of moneypunct provides two public constructors:
moneypunct()
moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)
locale's constructor calls the 2nd moneypunct constructor. Creating a proper _Locinfo is the crux of the problem as that information seems to be implementation specific. The linked Visual Studio Bug requests a way to construct a functional moneypunct without access to implementation details. In lieu of this information all moneypunct fields must be cooked up.
Since this question is about extending an expected working moneypunct the easiest way to do that would be to use an assignment operator or copy constructor. Bad news: both of those are deleted. So punct_facet(const money_punct&) will need to be written internally implementing the behavior of a copy constructor. The values that need to be copied correspond to all the virtual functions that need to be overridden and by punct_facet. In the end your class will end up looking similar to this:
template <typename T>
class punct_facet : public T {
protected:
typename T::string_type m_grouping;
typename T::string_type m_curr_symbol;
typename T::string_type m_positive_sign;
typename T::string_type m_negative_sign;
int m_frac_digits;
typename T::pattern m_pos_format;
typename T::pattern m_neg_format;
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
typename T::string_type do_grouping() const {
return m_grouping;
}
typename T::string_type do_curr_symbol() const {
return m_curr_symbol;
}
typename T::string_type do_positive_sign() const {
return m_positive_sign;
}
typename T::string_type do_negative_sign() const {
return m_negative_sign;
}
int do_frac_digits() const {
return m_frac_digits;
}
typename T::pattern do_pos_format() const {
return m_pos_format;
}
typename T::pattern do_neg_format() const {
return m_neg_format;
}
public:
punct_facet(const T& defaultFacet) : m_grouping(defaultFacet.grouping()),
m_curr_symbol(defaultFacet.curr_symbol()),
m_positive_sign(defaultFacet.positive_sign()),
m_negative_sign(defaultFacet.negative_sign()),
m_frac_digits(defaultFacet.frac_digits()),
m_pos_format(defaultFacet.pos_format()),
m_neg_format(defaultFacet.neg_format()) {}
};
EDIT:
This solution is cross platform but it is also unsatisfactory, because all the members that had to be added to punct_facet already exist in moneypunct. I am not aware of a clean workaround for this fattening. A compiler specific hack is available here: https://stackoverflow.com/a/31454039/2642059
This would result in a punct_facet that looked more like this given that Visual Studio places the v-table pointer as the first item in the object layout:
template <typename T>
class punct_facet : public T {
private:
void Init(const T* money){
const auto vTablePtrSize = sizeof(void*);
memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
}
protected:
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
public:
punct_facet(){
Init(&use_facet<T>(cout.getloc()));
}
punct_facet(const T* money){
Init(money);
}
};
Incidentally this implementation of punct_facet is not supported in Clang 3.6.0 but is supported in gcc 5.1.0: http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b
I have an application which creates simple music visualization animations. These animations are driven by nodes, and each node has a bunch of parameters that could have one of several types: int, float, color, etc. The parameters can either have a user-set value, or can be connected to the output of another node.
I'm currently using a templated type, along with std::function<>, like this:
#include <functional>
template <class PT>
class Param
{
public:
Param(PT value=PT()) : _value(value), _provider(nullptr) {}
void setValue(const PT &value) {_value = value;}
void setProvider(std::function<void(PT&)> provider) {_provider = provider;}
void getCurrentValue(PT &value) {
// update current member value
if (_provider)
_provider(_value);
value = _value;
}
private:
PT _value;
std::function<void(PT &value)> _provider;
};
I then instantiate parameters for an animated nodes like this:
class AnimationNode
{
public:
AnimationNode(Model *model = nullptr);
void evaluate();
private:
Param<int> _xoffset;
Param<int> _yoffset;
Param<float> _scale;
Param<ColorType> _color;
};
These parameters could be connected to a driver node, such as this one:
class SublevelMeter {
public:
SublevelMeter();
void setRange(Subrange &_range);
...
std::function<void(float&)> createProviderClosure();
private:
float _level;
...
}
std::function<void(float&)> SublevelMeter::createProviderClosure() {
return [this] (float &out) {out = _level;};
}
And connect one node to another by doing something like this:
AnimationNode::connectScaleToSublevel(SublevelMeter *slm) {
_scale->setProvider(slm->createProviderClosure());
}
The problem is, I'd like there to be an abstract Param type that I can pass to objects, so rather than the code above, I could pass a param to my SublevelMeter:
SublevelMeter::connectToParam(Param *param) {
param->setProvider(slm->createProviderClosure());
}
This would also help when writing the routines that create my GUI editor widgets: the editor could figure out the correct type by introspection of the Param.
But I'm not sure how to do this from a templated class, nor how the best way to implement the introspection in C++. (I'm coming at this from a python design background, which is perhaps encouraging me to think about this in a pythonic rather than C++ way; if there's a better way to approach this, I'd love to hear about it!)
I'm using Qt, so I've considered using QVariant, or other Qt Meta-Object stuff, but I'm not sure how to make that work, or if it would even be appropriate. (I'm not using Boost, and while I know it has certain type erasure facilities, I'm wary of wading into those waters...)
I'm interested in what the cleanest/"best" way to do this. Although efficiency is a consideration (getCurrentValue() is called many times per frame while the animation is playing) I can still probably afford run-time overhead of dynamic type stuff.
At least the first part of your question is solvable without abstract Param:
class SublevelMeter {
...
template<class PT>
void connectToParam(Param<PT> *param) {
param->setProvider(createProviderClosure<PT>());
}
// specialize this for different PTs
template<class PT>
std::function<void(PT&)> createProviderClosure();
}
If you really need to manipulate dynamic lists of Param-s, and you don't want to use any kind of RTTI, consider using Visitor pattern:
class Visitor;
class ParamBase
{
public:
virtual ~ParamBase() = default;
virtual void acceptVisitor(Visitor* v) = 0;
};
template <class PT>
class Param : public ParamBase
{
public:
...
void acceptVisitor(Visitor* v) override;
};
class Visitor {
public:
virtual ~Visitor() = default;
void visit(ParamBase* p) {
p->acceptVisitor(this);
}
virtual void visitParam(Param<float>* p) = 0;
// add more functions for other Params
};
class PrintVisitor : public Visitor {
public:
void visitParam(Param<float>* p) override {
std::cout << "visited Param<float>, value = " << p->getValue() << std::endl;
}
};
template<class PT>
void Param<PT>::acceptVisitor(Visitor* v) {
v->visitParam(this);
}
int main() {
std::unique_ptr<ParamBase> p(new Param<float>(123.4f));
std::unique_ptr<Visitor> v(new PrintVisitor());
v->visit(p.get());
return 0;
}
I implemented for you a simple class for the generic type management. This class is implemented without using template, so you can declare your variables and assign a value and a type directly at runtime. This implementation is very simple you should use it as reference to develop your own solution. In the following example I implemented the support for only 3 types: int, double and char* (C string). The main function shows you as to use the generic type class for both LVALUE and RVALUE assignment:
#include <stdio.h>
#include <stdlib.h>
enum Types {tInteger, tDouble, tString};
class TGenericType
{
private:
char m_Value[100];
Types m_Type;
protected:
public:
void operator=(int AValue)
{
m_Type = tInteger;
sprintf(m_Value, "%d", AValue);
}
operator int()
{
// try to convert the m_Value in integer
return atoi(m_Value); // the result depend by atoi() function
}
void operator=(double AValue)
{
m_Type = tDouble;
sprintf(m_Value, "%f", AValue);
}
operator double()
{
// try to convert the m_Value in double
return atof(m_Value); // the result depends by atof() function
}
void operator=(char* AValue)
{
m_Type = tString;
strcpy(m_Value, AValue);
}
operator char*()
{
return m_Value;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TGenericType LVar;
// int assignment LVar used as LVALUE
LVar = 10;
// int assignment LVar used as RVALUE
int i = LVar;
// Double assignment LVar used as LValue
LVar = 10.1;
// double assignment LVar used as RVALUE
double d = LVar;
// costant string assignment LVar used as RVALUE
LVar = "Ciao Mondo";
// string copying LVar used as const string RVALUE
char Buffer[100];
strcpy(Buffer, LVar);
return 0;
}
I tested above code on c++builder 32bit and c++builder (CLang) 64bit
If my solution answer your question, please check it as answered.
Ciao from Italy!
Angelo
I was searching for an implementation of extension methods in c++ and came upon this comp.std.c++ discussion which mentions that polymorphic_map can be used to associated methods with a class, but, the provided link seems to be dead. Does anyone know what that answer was referring to, or if there is another way to extend classes in a similar manner to extension methods (perhaps through some usage of mixins?).
I know the canonical C++ solution is to use free functions; this is more out of curiosity than anything else.
Different languages approach development in different ways. In particular C# and Java have a strong point of view with respect to OO that leads to everything is an object mindset (C# is a little more lax here). In that approach, extension methods provide a simple way of extending an existing object or interface to add new features.
There are no extension methods in C++, nor are they needed. When developing C++, forget the everything is an object paradigm --which, by the way, is false even in Java/C# [*]. A different mindset is taken in C++, there are objects, and the objects have operations that are inherently part of the object, but there are also other operations that form part of the interface and need not be part of the class. A must read by Herb Sutter is What's In a Class?, where the author defends (and I agree) that you can easily extend any given class with simple free functions.
As a particular simple example, the standard templated class basic_ostream has a few member methods to dump the contents of some primitive types, and then it is enhanced with (also templated) free functions that extend that functionality to other types by using the existing public interface. For example, std::cout << 1; is implemented as a member function, while std::cout << "Hi"; is a free function implemented in terms of other more basic members.
Extensibility in C++ is achieved by means of free functions, not by ways of adding new methods to existing objects.
[*] Everything is not an object.
In a given domain will contain a set of actual objects that can be modeled and operations that can be applied to them, in some cases those operations will be part of the object, but in some other cases they will not. In particular you will find utility classes in the languages that claim that everything is an object and those utility classes are nothing but a layer trying to hide the fact that those methods don't belong to any particular object.
Even some operations that are implemented as member functions are not really operations on the object. Consider addition for a Complex number class, how is sum (or +) more of an operation on the first argument than the second? Why a.sum(b); or b.sum(a), should it not be sum( a, b )?
Forcing the operations to be member methods actually produces weird effects --but we are just used to them: a.equals(b); and b.equals(a); might have completely different results even if the implementation of equals is fully symmetric. (Consider what happens when either a or b is a null pointer)
Boost Range Library's approach use operator|().
r | filtered(p);
I can write trim for string as follows in the same way, too.
#include <string>
namespace string_extension {
struct trim_t {
std::string operator()(const std::string& s) const
{
...
return s;
}
};
const trim_t trim = {};
std::string operator|(const std::string& s, trim_t f)
{
return f(s);
}
} // namespace string_extension
int main()
{
const std::string s = " abc ";
const std::string result = s | string_extension::trim;
}
This is the closest thing that I have ever seen to extension methods in C++. Personally i like the way it can be used, and possibly this it the closest we can get to extension methods in this language. But there are some disadvantages:
It may be complicated to implement
Operator precedence may be not that nice some times, this may cause surprises
A solution:
#include <iostream>
using namespace std;
class regular_class {
public:
void simple_method(void) const {
cout << "simple_method called." << endl;
}
};
class ext_method {
private:
// arguments of the extension method
int x_;
public:
// arguments get initialized here
ext_method(int x) : x_(x) {
}
// just a dummy overload to return a reference to itself
ext_method& operator-(void) {
return *this;
}
// extension method body is implemented here. The return type of this op. overload
// should be the return type of the extension method
friend const regular_class& operator<(const regular_class& obj, const ext_method& mthd) {
cout << "Extension method called with: " << mthd.x_ << " on " << &obj << endl;
return obj;
}
};
int main()
{
regular_class obj;
cout << "regular_class object at: " << &obj << endl;
obj.simple_method();
obj<-ext_method(3)<-ext_method(8);
return 0;
}
This is not my personal invention, recently a friend of mine mailed it to me, he said he got it from a university mailing list.
The short answer is that you cannot do that. The long answer is that you can simulate it, but be aware that you'll have to create a lot of code as workaround (actually, I don't think there is an elegant solution).
In the discussion, a very complex workaround is provided using operator- (which is a bad idea, in my opinion). I guess that the solution provided in the dead link was more o less similar (since it was based on operator|).
This is based in the capability of being able to do more or less the same thing as an extension method with operators. For example, if you want to overload the ostream's operator<< for your new class Foo, you could do:
class Foo {
friend ostream &operator<<(ostream &o, const Foo &foo);
// more things...
};
ostream &operator<<(ostream &o, const Foo &foo)
{
// write foo's info to o
}
As I said, this is the only similar mechanism availabe in C++ for extension methods. If you can naturally translate your function to an overloaded operator, then it is fine. The only other possibility is to artificially overload an operator that has nothing to do with your objective, but this is going to make you write very confusing code.
The most similar approach I can think of would mean to create an extension class and create your new methods there. Unfortunately, this means that you'll need to "adapt" your objects:
class stringext {
public:
stringext(std::string &s) : str( &s )
{}
string trim()
{ ...; return *str; }
private:
string * str;
};
And then, when you want to do that things:
void fie(string &str)
{
// ...
cout << stringext( str ).trim() << endl;
}
As said, this is not perfect, and I don't think that kind of perfect solution exists.
Sorry.
To elaborate more on #Akira answer, operator| can be used to extend existing classes with functions that take parameters too. Here an example that I'm using to extend Xerces XML library with find functionalities that can be easily concatenated:
#pragma once
#include <string>
#include <stdexcept>
#include <xercesc/dom/DOMElement.hpp>
#define _U16C // macro that converts string to char16_t array
XERCES_CPP_NAMESPACE_BEGIN
struct FindFirst
{
FindFirst(const std::string& name);
DOMElement * operator()(const DOMElement &el) const;
DOMElement * operator()(const DOMElement *el) const;
private:
std::string m_name;
};
struct FindFirstExisting
{
FindFirstExisting(const std::string& name);
DOMElement & operator()(const DOMElement &el) const;
private:
std::string m_name;
};
inline DOMElement & operator|(const DOMElement &el, const FindFirstExisting &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement &el, const FindFirst &f)
{
return f(el);
}
inline DOMElement * operator|(const DOMElement *el, const FindFirst &f)
{
return f(el);
}
inline FindFirst::FindFirst(const std::string & name)
: m_name(name)
{
}
inline DOMElement * FindFirst::operator()(const DOMElement &el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline DOMElement * FindFirst::operator()(const DOMElement *el) const
{
if (el == nullptr)
return nullptr;
auto list = el->getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
return nullptr;
return static_cast<DOMElement *>(list->item(0));
}
inline FindFirstExisting::FindFirstExisting(const std::string & name)
: m_name(name)
{
}
inline DOMElement & FindFirstExisting::operator()(const DOMElement & el) const
{
auto list = el.getElementsByTagName(_U16C(m_name));
if (list->getLength() == 0)
throw runtime_error(string("Missing element with name ") + m_name);
return static_cast<DOMElement &>(*list->item(0));
}
XERCES_CPP_NAMESPACE_END
It can be used this way:
auto packetRate = *elementRoot | FindFirst("Header") | FindFirst("PacketRate");
auto &decrypted = *elementRoot | FindFirstExisting("Header") | FindFirstExisting("Decrypted");
You can enable kinda extension methods for your own class/struct or for some specific type in some scope. See rough solution below.
class Extensible
{
public:
template<class TRes, class T, class... Args>
std::function<TRes(Args...)> operator|
(std::function<TRes(T&, Args...)>& extension)
{
return [this, &extension](Args... args) -> TRes
{
return extension(*static_cast<T*>(this), std::forward<Args>(args)...);
};
}
};
Then inherit your class from this and use like
class SomeExtensible : public Extensible { /*...*/ };
std::function<int(SomeExtensible&, int)> fn;
SomeExtensible se;
int i = (se | fn)(4);
Or you can declare this operator in cpp file or namespace.
//for std::string, for example
template<class TRes, class... Args>
std::function<TRes(Args...)> operator|
(std::string& s, std::function<TRes(std::string&, Args...)>& extension)
{
return [&s, &extension](Args... args) -> TRes
{
return extension(s, std::forward<Args>(args)...);
};
}
std::string s = "newStr";
std::function<std::string(std::string&)> init = [](std::string& s) {
return s = "initialized";
};
(s | init)();
Or even wrap it in macro (I know, it's generally bad idea, nevertheless you can):
#define ENABLE_EXTENSIONS_FOR(x) \
template<class TRes, class... Args> \
std::function<TRes(Args...)> operator| (x s, std::function<TRes(x, Args...)>& extension) \
{ \
return [&s, &extension](Args... args) -> TRes \
{ \
return extension(s, std::forward<Args>(args)...); \
}; \
}
ENABLE_EXTENSIONS_FOR(std::vector<int>&);
This syntactic sugar isn't available in C++, but you can define your own namespace and write pure static classes, using const references as the first parameter.
For example, I was struggling using the STL implementation for some array operations, and I didn't like the syntaxis, I was used to JavaScript's functional way of how array methods worked.
So, I made my own namespace wh with the class vector in it, since that's the class I was expecting to use these methods, and this is the result:
//#ifndef __WH_HPP
//#define __WH_HPP
#include <vector>
#include <functional>
#include <algorithm>
namespace wh{
template<typename T>
class vector{
public:
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator, const std::function<T(T,T)> &functor){
T accumulator = accumulatorInitiator;
for(auto &element: array) accumulator = functor(element, accumulator);
return accumulator;
}
static T reduce(const std::vector<T> &array, const T &accumulatorInitiator){
return wh::vector<T>::reduce(array, accumulatorInitiator, [](T element, T acc){return element + acc;});
}
static std::vector<T> map(const std::vector<T> &array, const std::function<T(T)> &functor){
std::vector<T> ret;
transform(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static std::vector<T> filter(const std::vector<T> &array, const std::function<bool(T)> &functor){
std::vector<T> ret;
copy_if(array.begin(), array.end(), std::back_inserter(ret), functor);
return ret;
}
static bool all(const std::vector<T> &array, const std::function<bool(T)> &functor){
return all_of(array.begin(), array.end(), functor);
}
static bool any(const std::vector<T> &array, const std::function<bool(T)> &functor){
return any_of(array.begin(), array.end(), functor);
}
};
}
//#undef __WH_HPP
I wouldn't inherit nor compose a class with it, since I've never been able to do it peacefully without any side-effects, but I came up with this, just const references.
The problem of course, is the extremely verbose code you have to make in order to use these static methods:
int main()
{
vector<int> numbers = {1,2,3,4,5,6};
numbers = wh::vector<int>::filter(numbers, [](int number){return number < 3;});
numbers = wh::vector<int>::map(numbers,[](int number){return number + 3;});
for(const auto& number: numbers) cout << number << endl;
return 0;
}
If only there was syntactic sugar that could make my static methods have some kind of more common syntax like:
myvector.map([](int number){return number+2;}); //...