named function parameters using strong typedefing like mechisms.
This message shows how to make the following code legal C++:
object.set()(Data(1),WithinFoobar(x));
Making C++ look more like the self documenting Objective C. (Though I
think I like having the power of C++ over having the weak typing of
Objective C.)
#include "stdafx.h"
// This program demostrates a way to make strong typedefs in C++. It
is
// unforunate that C++ does not have strong typedef's as well as weak
// typedefs built in. Strong typedefing allow C++ look more like
// Objective C. I would enjoy hearing whether anyone else likes
// this techinque. Of course, some of this might just be considered
// Rube-Goldberg by some, but I really like proxies and the syntax
// of Objective C though I have not programmed in it (just read about
it).
namespace StrongTypedefLibrary
{
// This one allows a constant strong typedef.
template<typename T> class ConstDataReferencer
{
T const& data;
public:
typedef T data_type;
explicit ConstDataReferencer(T const& r) : data(r) {}
T const& get() const { return data; }
};
// This one allows a mutable strong typedef.
template<typename T> class MutableDataReferencer
{
T& data;
public:
typedef T data_type;
explicit MutableDataReferencer(T& r) : data(r) {}
T& get() { return data; }
};
}
// If there were a __UNIQUE__ macro in C++ then a second template
// parameter could be added to the DataReferencer types instead
// of having to encode in the Class, but the Class makes it Unique
// for infix notation but allowing the same parameter names though
// __UNIQUE__ would be better. (Not sure infix is right word here,
// but look at the uses of the operator call for information on what
// I mean.)
#define STRONGTYPEDEF(Class,TYPE,NEWTYPE,DR) \
struct Class { \
typedef StrongTypedefLibrary::DR##DataReferencer<TYPE> NEWTYPE; }; \
typedef Class::NEWTYPE NEWTYPE;
// This is a macro that allows the use of one parameter operator calls
// so that parameters may be named like they are named in
// objective C. (Though still a different syntax.)
#define PROXY1(MEMBER,METHOD,TPROXY1) \
class Proxy##METHOD { \
private: TPROXY1::data_type& data; \
public: \
class Proxy##METHOD##Result; \
Proxy##METHOD(TPROXY1::data_type& r) : data(r) {} \
Proxy##METHOD##Result operator()(TPROXY1); \
}; \
Proxy##METHOD METHOD() { return Proxy##METHOD(this->MEMBER); }
// This is a macro that allows the use of two parameter operator calls
// so that parameters may be named like they are named in
// objective C. (Though still a different syntax.)
#define PROXY2(MEMBER1,MEMBER2,METHOD,TPROXY1,TPROXY2) \
class Proxy##METHOD { \
private: \
TPROXY1::data_type& data1; \
TPROXY2::data_type& data2; \
public: \
class Proxy##METHOD##Result; \
Proxy##METHOD(TPROXY1::data_type& d1, TPROXY2::data_type& d2) :
data1(d1), data2(d2) {} \
Proxy##METHOD##Result operator()(TPROXY1, TPROXY2); \
}; \
Proxy##METHOD METHOD() { return Proxy##METHOD(this->MEMBER1,
this->MEMBER2); }
namespace AFineName { class C
{
private:
int first; int second;
public:
C(int f, int s) : first(f), second(s) {}
// Strong typedefs:
STRONGTYPEDEF(InnerDataTypeA, int, FirstInt, Const);
STRONGTYPEDEF(InnerDataTypeB, int, SecondInt, Mutable);
PROXY2(first,second,a,FirstInt,SecondInt);
PROXY1(first,b,FirstInt);
};
// These result classes allow the operator calls to return data.
// It is not possible to have a void operator call (ProxybResult
// is the closest one to NULL as possible.)
class C::Proxya::ProxyaResult {
public:
ProxyaResult const& operator=(ProxyaResult const&)
{ std::cout << "ProxyaResult" << std::endl; return *this; }
};
class C::Proxyb::ProxybResult { };
C::Proxya::ProxyaResult C::Proxya::operator ()(C::FirstInt fi,
C::SecondInt si)
{
data1 = fi.get();
data2 = si.get()++;
return ProxyaResult();
}
C::Proxyb::ProxybResult C::Proxyb::operator ()(C::FirstInt fi)
{
data = fi.get();
return ProxybResult();
}
}
int _tmain(int argc, _TCHAR* argv[])
{
AFineName::C area(1,2);
int second = 13;
AFineName::C::Proxya::ProxyaResult result;
{ using namespace AFineName;
// Is this not pretty syntax:
result = area.a()(C::FirstInt(10),C::SecondInt(second));
// And this too:
area.b()(C::FirstInt(201));
}
// Will be 14.
std::cout << second << std::endl;
return 0;
}
// Sincerely, Mark Barkell 2006 AD June 11. 2:49 AM
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]