Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Enforcing Compile-time Constraints-2 : Page 2




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Presenting the Problem
Suppose your app needs to interface with a non-C++ module written in C or SQL. To do so, you need to ensure that all objects passed to the non-C++ module have POD types. Alas, the definition of a POD type is rather evasive:

struct S1 { int x;}; class S2 { public: void func(); }; union S3 { struct { int x, y; } t; char c[4];}; struct S4 : S1, S2 {};

The above are all POD types. However, the following aren't:

struct C1 { virtual void func(); //has a virtual function }; struct C2 { struct T{ int x, y; }; ~C2(); //has a destructor }; struct C3 : virtual S1 {} ; //has a virtual base class

Several programming idioms rely on the distinction between POD and non-POD types. The standard macro offsetof() (defined in <csstddef>) is an example. The following expression:

size_t nbytes = offsetof (S, mem);

returns the offset in bytes of the member mem. According to the C++ standard, S must be a POD class, struct, or union. Otherwise, the results are undefined. Your task is therefore to write a constraint that automatically distinguishes between POD and non-POD types at compile-time. When the "must be POD type" constraint is violated, the compiler should issue an intelligible error message.

Implementing a Constraint
A constraint is essentially an expression or declaration within a member function of a class template. When the constraint is violated, the said expression triggers a compilation error. The challenging part is to find the right compile-time expression(s) that will fire when the constraint is violated. Familiarity with the C++ standard certainly wouldn't hurt here. Fortunately, the standard states in clause 9.5 that a non-POD object shall not be a member of a union. Eureka! Take advantage of this restriction by creating a union whose sole member is the object you want to test:

template <class T> struct POD_test { POD_test() { union { T t; //T must be a POD type } u; } };

Compilers generate code only for member functions that are actually called, either implicitly or explicitly. Therefore, implementing the constraint inside the constructor or destructor of a class template will guarantee its compile-time evaluation in every instance (later we will see how to improve this design).

To test the code, instantiate as many specializations as you like using diverse template arguments:

//the following three pass compilation POD_test <int> pi; POD_test <S1> ps1; POD_test <S4> ps4; //these ones fail POD_test <std::string> pstr; POD_test <C1> pc1; POD_test <C2> pc2;

As expected, the compiler issues error messages for the last three instances because their template arguments aren't POD objects.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date