The problem is: There are some math expressions, which have +/-/*// operators. But they can be implemented in different math libraries. And different math libraries implementation cannot be calculated directly. How to design the expression classes?
Design by having a base class:
class Expr;
class LPExpr: public Expr
{
operate();
};
class XXExpr: public Expr
{
operate();
};
Expr operator+(const Expr&, const Expr&);
The difficulty is, in operator+, since they may be in different implementation, it may need to open up some common interface in Expr. But somtimes, the value needs a specific class type interface to retrieve.
By Template:
The below implementation is done by template. it can solve the problem of different types of expressions calculations because the implementation is done in template specialization, no need to be defined in definitions. The design defines almost the thinnest interface for expressions. What we want are, the class name and the operators only. Especially, it is suitable for the operations implementations between base classes.
class LPType;
class XXType;
template<class T>
class Expr;
template<class T>
class Factory
{
public:
Expr<T> * create();
};
template<class T>
Expr<T> operator+(const Expr<T>&, const Expr<T> &);
template<>
class Expr<LPType>
{
public:
Expr()
{
cout << "Expr() LPType" << endl;;
}
private:
int m_env;
};
template<>
class Factory<LPType>
{
public:
Expr<LPType>* create()
{
cout << "creating expr LPType" << endl;
return new Expr<LPType>();
}
};
template<>
Expr<LPType> operator+(const Expr<LPType>&, const Expr<LPType> &)
{
Expr<LPType> lpType;
cout << "operator+ LPType";
lpType.m_env;
return lpType;
}
template<>
class Expr<XXType>
{
public:
Expr()
{
cout << "Expr() XXType" << endl;;
}
};
template<>
class Factory<XXType>
{
public:
Expr<XXType>* create()
{
cout << "creating expr XXType" << endl;
return new Expr<XXType>();
}
};
template<>
Expr<XXType> operator+(const Expr<XXType>&, const Expr<XXType> &)
{
Expr<XXType> lpType;
cout << "operator+ XXType";
return lpType;
}
int main()
{
Factory<LPType> lpFactory;
Expr<LPType>* lpType1 = lpFactory.create();
Expr<LPType>* lpType2 = lpFactory.create();
*lpType1 + *lpType2;
Factory<XXType> xxFactory;
Expr<XXType>* xxType1 = xxFactory.create();
*lpType1 + *xxType1; // cannot compiled
return 0;
}
Wednesday, 19 September 2012
Thursday, 6 September 2012
why BOOST_STRONG_TYPEDEF?
The source code below:
template<>
ROKeyIndex2 updateIndex<ROKeyIndex2, ROKeyIndex>(const ROKeyIndex& keyIndex)
{
ROKeyIndex2 index2(keyIndex, 0);
return index2;
}
template<>
ROKeyIndex2 updateIndex<ROKeyIndex2, ROUnIndex>(const ROUnIndex& keyIndex)
{
ROKeyIndex2 index2(0, keyIndex);
return index2;
}
It uses template specialization to differentiate two kinds of implementation.
However, since they are in the same type int,
typedef int ROKeyIndex;
typedef int ROUnIndex;
In VS2010, it will report duplicated implementations in linking phase.
But they are really in different meaning in application level except they are defined in the same type.
How to solve?
by using strong_typedef, it will force them to be in different types, which makes those template specialization functions be different.
#include <boost/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(int, ROVarIndex);
BOOST_STRONG_TYPEDEF(int, ROUnIndex);
In the boost header file,
template<>
ROKeyIndex2 updateIndex<ROKeyIndex2, ROKeyIndex>(const ROKeyIndex& keyIndex)
{
ROKeyIndex2 index2(keyIndex, 0);
return index2;
}
template<>
ROKeyIndex2 updateIndex<ROKeyIndex2, ROUnIndex>(const ROUnIndex& keyIndex)
{
ROKeyIndex2 index2(0, keyIndex);
return index2;
}
It uses template specialization to differentiate two kinds of implementation.
However, since they are in the same type int,
typedef int ROKeyIndex;
typedef int ROUnIndex;
In VS2010, it will report duplicated implementations in linking phase.
But they are really in different meaning in application level except they are defined in the same type.
How to solve?
by using strong_typedef, it will force them to be in different types, which makes those template specialization functions be different.
#include <boost/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(int, ROVarIndex);
BOOST_STRONG_TYPEDEF(int, ROUnIndex);
In the boost header file,
explicit D(const T t_) : t(t_) {};
Wednesday, 5 September 2012
QT QObject usage and QT Makefile genereation on Linux
To use the QT Signal/Slot mechanism, sometimes you may want to make your classes to be subclasses of QObject.
It should be straight forward to inherit from QObject class and use marcro QObject to achieve the ability of QObject.
Note: The inherited QObject should be defined in a separate header file and cannot be defined in cpp. Because QT will generate some mock files by the existing header files, and those mock files may contain some QObject function implementations.
And for QT Makefile generation on Linux, the command is
$(QT_PATH)/bin/qmake -spec $(QT_PATH)/mkspecs/linux-g++ -o Makefile.linux proj.pro.
And proj.pro can be generated by QTCreator.
It should be straight forward to inherit from QObject class and use marcro QObject to achieve the ability of QObject.
Note: The inherited QObject should be defined in a separate header file and cannot be defined in cpp. Because QT will generate some mock files by the existing header files, and those mock files may contain some QObject function implementations.
And for QT Makefile generation on Linux, the command is
$(QT_PATH)/bin/qmake -spec $(QT_PATH)/mkspecs/linux-g++ -o Makefile.linux proj.pro.
And proj.pro can be generated by QTCreator.
One way to access internal server
One case, Internal server is deployed in one Data Center and it is behind firewall and has internal IP address.
Besides using NAT, if the internal server can access to Internet, we can use some application layer remote control software to control it.
Besides using NAT, if the internal server can access to Internet, we can use some application layer remote control software to control it.
Subscribe to:
Comments (Atom)