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
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.
-edit- I narrowed it down. Reproducible: Why does passing this object in C break my code?
My app is not working properly after i made a change. I got a warning in msvc but not in gcc.
Heres a repo of the warning.
warning C4190: 'fnA' has C-linkage specified, but returns UDT 'Test' which is incompatible with C
#include <type_traits>
template<class T>
class Test{
T t;
};
typedef Test<int> A;
//static_assert(std::is_pod<A>::value, "Not a POD"); //fails in msvc 2010
static_assert(sizeof(A) == sizeof(int), "");
static_assert(sizeof(A) == sizeof(void*), "");
extern "C" {
A fnA(A v) { return v; }
}
int main() {
A a;
fnA(a);
}
AFAIK there should be no reason why i can't use Test as a return value; This may not be the problem but this may be the problem. I can't figure out the problem but i get runtime oddities that i can not reproduce (both gcc and msvc). I suspected the problem would be MyString is corrupted but it appears that isnt the case which made me quite confused. Heres my wrapper. MyString is >8bytes and i need to hand this off to C code which returns everything by int unfortunately. Which is why i put the static assert to see if the class size is what i expected. Now that size/splicing is handled, i'm still completely like WTF!?! Why does that warning exist and is there anything i can possibly do to fix it?
Even writing class Test{ T t; }; causes the warning however struct fixes it. struct with private breaks it and i need t to be private.
OK! After I removed the constructors in WrappedPointer and changed the class to struct (which makes lhs public). It runs perfectly in GCC and MSVC. Changing struct WrappedPointer to class WrappedPointer breaks my code. WTF!?! This is a debug build too, not optimized. Why on earth does changing the keyword struct to class break the code!?! WTF!?! BUT that change doesnt break gcc. Using non default constructors break gcc...
template <class T>
struct WrappedPointer {
//private:
T* lhs;
public:
void SetLHS(T*v) { lhs=v; }
//WrappedPointer(){}
//WrappedPointer(T*value) : lhs(value){}
//WrappedPointer(const WrappedPointer&v) : lhs(v.lhs){}
T* operator->() const { return lhs; }
T* operator*() const { return lhs; }
template<class TT>
bool operator==(TT t) const { return *lhs==t; }
template<class TT>
bool operator!=(TT t) const { return *lhs!=t; }
bool operator==(int v) const { myassert2(v==0); return lhs==0; }
bool operator!=(int v) const { myassert2(v==0); return lhs!=0; }
bool operator==(const WrappedPointer&t) const { return *lhs==*t; }
bool operator!=(const WrappedPointer&t) const { return *lhs!=*t; }
}
typedef WrappedPointer<MyString> String;
//typedef MyString* String;
static_assert(sizeof(String) == sizeof(int), "");
static_assert(sizeof(String) == sizeof(void*),"");
The external "C" marks the function to have C linkage and disables name mangling. Now the issue in your function is that the argument is a template (the typedef only creates an alias in the current translation unit, A is still Test<int> for all purposes), and that name must be mangled.
extern "C" {
A fnA(A v) { return v; }
}
This says that fnA is a C function. C does not have object-oriented programming, or templates. The function uses both. Therefore, it cannot link as a C function.
Classes are not valid in C.
Templates are not valid in C.
Templated classes are certainly not valid in C.
Pick your language and stick to it!
In Checking a member exists, possibly in a base class, C++11 version, we developed a C++11 version of the classical member-checking type-trait from SFINAE to check for inherited member functions that also works with C++11 final classes, but uses C++11 features (namely, decltype), too:
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
static_assert(sizeof(Yes) != sizeof(No));
template<class C>
static decltype(std::declval<C>().resize(10), Yes()) test(int);
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
MSVC has had final as a non-standard extension named sealed since VS2005, but decltype has only been added in VS2010. That leaves VS2005 and 2008 where a class that is marked as sealed still breaks the classical type-trait and the C++11 version cannot be used.
So, is there a way to formulate has_resize_method such that it works on VC2005/08 sealed classes, too?
Obviously, just as using C++11-only features to work around a C++11-only problem (final) is fine, so would be using VS-only extensions to work around the VS2005/08-only problem of sealed classes, but if there's a solution that works for all three sets of compilers {C++11,{VS2005,VS2008},all others}, that would be cool, but probably too much to ask for :)
I was able to come up with a solution that works in all major compilers. Sadly, there is a preprocessor check for MSVC because it complains about the solution for other compilers. The main difference is that MSVC does not accept function pointers inside sizeof() and conversely, GCC does not seem to accept (&C::resize == 0) in the check. Clang happily accepts both.
#include <iostream>
class Base {
public:
void resize(int, int, int) { }
};
class Derived : public Base {
};
class Unrelated { };
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
#ifdef _MSC_VER
template <class C>
static Yes test(char (*)[(&C::resize == 0) + 1]);
#else
template <class C>
static Yes test(char (*)[sizeof(&C::resize) + 1]);
#endif
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
int main() {
std::cout << (has_resize_method<Base>::value ? "Base has method resize" : "Base has NO method resize") << std::endl;
std::cout << (has_resize_method<Derived>::value ? "Derived has method resize" : "Derived has NO method resize") << std::endl;
std::cout << (has_resize_method<Unrelated>::value ? "Unrelated has method resize" : "Unrelated has NO method resize") << std::endl;
return 0;
}
Output:
Base has method resize
Derived has method resize
Unrelated has NO method resize
Tested on GCC 4.5.3, GCC 4.3.4, Clang 3.0, Visual C++ 2008 and Visual C++ 2010. I don't have access to Visual C++ 2005 but I think it will work there, too. It also compiles on Comeau Online but I cannot guarantee it produces a correct output there.
Works with both final and __sealed classes.
Note though that it checks not only for member functions but for member pointers in general. You might want to add additional checks such as boost::is_member_function_pointer if this behavior is unwanted. Similarly, you might want to add checks for number of arguments/argument types/result types - again, boost will be very helpful here, esp. boost type decomposition.
MSVC has a special statement __if_exists since vs2005. MSDN Link here. You can use it to check the member function name directly. And then check the signature. Following is a simple foo detection example:
template <typename T, typename U>
int8_t FooCheck( void(T::*)(U) )
{
return 0;
}
template <typename T>
int16_t FooCheck( void(T::*)(double))
{
return 0;
}
template <typename T>
int32_t FooCheck(void(T::*)(int))
{
return 0;
}
template <typename T>
class Detector
{
public:
__if_exists(T::foo)
{
enum
{
value = sizeof(FooCheck(&T::foo))
};
}
__if_not_exists(T::foo)
{
enum
{
value = 0
};
}
};
std::cout << Detector<Class>::value << std::endl;
I was implementing (for training purpose) a Bubble Sort template function:
template<typename iterInput,
typename predicate>
void BubbleSort(iterInput first1,iterInput last1,predicate func)
{
bool swapped(false);
do
{
swapped = false;
iterInput begin = first1;
iterInput beginMinus = first1;
++begin;
for (;begin != last1; begin++,beginMinus++)
{
if (func(*beginMinus,*begin) )
{
std::swap(*beginMinus,*begin);
swapped = true;
}
}
}
while(swapped);
}
When I have realized that this function will not work for class with no assignment operator, like this one (forgive me for the bad name):
class NoCopyable
{
public:
explicit NoCopyable(int value) : value_(value) {}
NoCopyable(const NoCopyable& other) : value_(other.value_) {}
~NoCopyable() {}
bool operator<(const NoCopyable& other) { return value_ < other.value_; }
void setValue(int value) { value_ = value; }
std::ostream& print(std::ostream& os) const { return os << value_; }
private:
NoCopyable& operator=(const NoCopyable& other);
int value_;
};
std::ostream& operator<<(std::ostream& os, const NoCopyable& obj)
{
return obj.print(os);
}
struct PrintNoCopyable
{
void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; }
};
The compiler raises this error Error 1 error C2248: 'NoCopyable::operator =' : cannot access private member declared in class 'NoCopyable'
So, I have slightly modify the code using instead of the std::swap function my version of the swap function, here is the code:
template<typename T1,
typename T2>
void noAssignmentSwap(T1& t1,T2& t2)
{
T1 temp(t1);
t1.~T1();
new (&t1) T1(t2);
t2.~T2();
new (&t2) T2(temp);
}
The code compiles and gives the right result. However I am not completely sure, I remember a Sutter's article that suggest you to avoid playing with the objects life time. The article just warns you by playing with fire without actually giving you any real reason. I can see problem in exception safety if the copy constructor of T1 or T2 can throw. However there is the same problem in the standard version if the assignment operator is allowed to throw.
Here the question, can you see any possible drawbacks in this version of swap?
Cheers
Apart from anything else, if a class does not have an assignment operator, its designer probably did not intend it to be swapped. If they did that, they probably disabled copy construction too, so your new swap function still won't work.
As for your assertion that Standard Library containers do not need assignment - that is true so long as you don't want to actually do anything useful with them. Does this code compile for you?
#include <vector>
using namespace std;
struct A {
private:
void operator=( const A &);
};
int main() {
vector <A> v;
v.push_back( A() );
v[0] = A(); // assignment needed here
}
I think it won't.
The difference is that when the assignment operator fails, you still have the same number of objects.
If you destroy one object and fail to create a new one, one object is lost! If it was part of a container, the container's state is probably also invalid.
You need a copy ctor instead of an assignment operator, but the two are sufficiently similar that at least in a typical case, you'll have both or you'll have neither. IOW, I don't think this generally accomplishes much.
I'd class it right along side the xor-swap trick: interesting, but generally useless.
It might be confusing to a future maintainer of the code.
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.