3

I'm making a cross-platform library implementing several basic primitives on several platforms. To verify that every implementation of a primitive (i.e. class) provides core members required on all platforms I use the following construct:

template<typename _Ty> int _MethodVerifyHelper(_Ty);
#define ENSURE_MEMBER_DECL(className, methodName, returnType, ...) typedef char __PROTOTYPE_VERIFIER__[sizeof(_MethodVerifyHelper<returnType (className::*)(__VA_ARGS__)>(&className::methodName))]

Then I write something like this:

ENSURE_MEMBER_DECL(Event, TryWait, bool, unsigned);

So if the Event class has no bool TryWait(unsigned) method, we'll get a compilation error here.

The question is: is there a similar syntax in C++ to declare pointers to constructors? I want to have a statement that causes a compile-time error if a class does not provide a constructor with given argument types.

Ivan Shcherbakov
  • 2,063
  • 14
  • 23
  • possible duplicate of [Check at compile time class constructor signature](http://stackoverflow.com/questions/949432/check-at-compile-time-class-constructor-signature) – Björn Pollex Aug 01 '12 at 10:22
  • Off-topic, but you shouldn't use [reserved names](http://stackoverflow.com/questions/228783) like `_Ty` and `_MethodVerifyHelper`. – Mike Seymour Aug 01 '12 at 10:58

2 Answers2

10

There's no way you can take the address of a constructor, but you can easily get a compile time error if an object can't be constructed with a given set of arguments:

typedef int dummyToTriggerError[ sizeof( T( arg1, arg2, arg3 ) ) ];

The essential part is, of course, the sizeof expression, which contains a construction of the object which will never be evaluated, but which must be legal. It's wrapped in a typedef to ensure that it won't generate any code, ever.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
3

No, you cannot take a pointer to a constructor.

The way to ensure a particular constructor is provided would be to simulate a call to the constructor inside a non-execution context (e.g. sizeof):

static_assert(sizeof(className(std::declval<arg1_type>(), std::declval<arg2_type>())) > 0, "");
Xeo
  • 129,499
  • 52
  • 291
  • 397
ecatmur
  • 152,476
  • 27
  • 293
  • 366