# [C++ ] Library less function enabler (no Boost, Loki, etc.)

This topic is 3298 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

As part of a larger project I am trying to develop a function enabler (Dr Dobb's - Function Overloading Based on Arbitrary Properties of Types) to enable a function intended for use with a point class, the implementation and name of which are unknown. I don't want to use any library like BOOST or Loki, etc.. So far I have the following:
// constraint
template<class T1> struct must_have_XYZ {
~must_have_XYZ() { void(*p)() = constraints; }
private:
static void constraints() {
T1& b = *new T1;
b.x = b.y = b.z;
}
};

// [1]
template< typename T >
struct supports_XYZ {
static const bool value = false;
};


// [2]
template<typename T>
struct supports_XYZ<must_have_XYZ<T> > {
static const bool value = true;
};

int main() {
bool b1 = supports_XYZ<Pt >::value;
bool b2 = supports_XYZ<int >::value;

return 0;
}


I am trying to use the constraint to limit the instantiation of the supports_XYZ template to [2] but, regardless of the type, [1] is always instantiated (both b1 and b2 are set to false). Since I don't know the name of the point type/class ahead of time I can't partially specialise like so:
template<>
struct supports_XYZ<Pt > { // only useful if Pt is defined
// won't work for Point or P3d or whatever
static const bool value = true;
};


Hence the attempt to use a constraint. Am I barking up the wrong tree? Is this even possible? Any help with this much appreciated. A5

##### Share on other sites
As far as I know there's no totally cross-platform way to do this (if so please correct me!). Something such as the following should detect the presence of a member "x" I believe on a compliant compiler:

typedef char (&yes)[1];typedef char (&no)[2];template <typename T>struct has_member_x{	template <size_t> struct helper { };	template <typename U>	static yes test(helper<sizeof(&U::x)> *);	template <typename>	static no test(...);	static const bool value = sizeof(test<T>(0)) == sizeof(yes);};struct Point1 { float x; };struct Point2 { float z; };// has_member_x<Point1>::value should be 1// has_member_x<Point2>::value should be 0

To make this more useful, you'd probably want to define a macro that declares the has_member_foo struct for each member you want to test for, and probably another macro to wrap the test itself.

Note that in general this is a tricky area as it depends on how the compiler treats sizeof expressions, which is by no means standard. See here for more info.

##### Share on other sites
Quote:
 Original post by Amnesiac5I am trying to use the constraint to limit the instantiation of the supports_XYZ template to [2] but, regardless of the type, [1] is always instantiated (both b1 and b2 are set to false).

The article does something clearly different from your code: template instantiation fails controllably thanks to an artificial dependence from a typedef that the "function enabler" can be made to contain or not.

Boolean constants like yours can be used to choose between the disabler and the enabler, but there are neither if statements nor boolean template parameters in your code.

Defining supports_XYZ<must_have_XYZ<T> > makes very little sense if you don't actually instantiate any must_have_XYZ<> (e.g. must_have_XYZ<Pt>).

The concern about not knowing the class name is, I'm afraid, absurd: if you don't know what classes posterity will try to use with the templates you are writing now, you cannot tell what template specializations will be needed (and you aren't even certain you'll need to mess with overloading).

In the specific case of your example, it's both hard to imagine how constraints() might be adapted to fundamentally different point representations and easy to see that it should really operate on a decently explicit point interface.
If the template function referred to accessor methods for the three coordinates you could make simple and efficient adapters for different point-like classes rather than unnecessarily assuming that point-like classes have public fields x,y and z.

##### Share on other sites
Quote:
 Original post by d00fusAs far as I know there's no totally cross-platform way to do this (if so please correct me!). Something such as the following should detect the presence of a member "x" I believe on a compliant compiler:*** Source Snippet Removed ***Note that in general this is a tricky area as it depends on how the compiler treats sizeof expressions, which is by no means standard.

Thanks for the feedback.

Hmm, this looks like a step in the right direction. I seem to remember seeing sizeof used in similar fashion elsewhere, but blowed if I can remember where.

Any references for this?

Visual Studio spits out an "error C2070: '': illegal sizeof operand" compilation error for sizeof(test<T>(0)) if I include the line:
has_member_x<Point1 >::value;
is this the tricky area you're talking about?

has_member_x<int >::value;
does indeed evaluate to false.

A5

##### Share on other sites
In most C++03 implementations, you cannot detect whether some expressions are valid for some types at compile-time.
You need support for SFINAE for expressions to do this.

All you can detect is whether some class type provides some members using the aforementioned kind of trick.
Note it is better to use helper<U, &U::x> instead, as that is actually guaranteed to work and is much more useful since you can check the type of &U::x is what you want.

##### Share on other sites
Quote:
 Original post by Amnesiac5Visual Studio spits out an "error C2070: '': illegal sizeof operand" compilation error for sizeof(test(0)) if I include the line:has_member_x::value;is this the tricky area you're talking about?

Yes, in this case I think VC++ doesn't support the technique. GCC and Comeau both do however. From memory in VC++ there is a compiler extension to perform the same job, __if_exists or something similar. If you are desperate to go down this route, you could conditionally compile the correct version for the compiler you're using.

##### Share on other sites
Quote:
Original post by LorenzoGatti
Quote:
 Original post by Amnesiac5I am trying to use the constraint to limit the instantiation of the supports_XYZ template to [2] but, regardless of the type, [1] is always instantiated (both b1 and b2 are set to false).

The article does something clearly different from your code: template instantiation fails controllably thanks to an artificial dependence from a typedef that the "function enabler" can be made to contain or not.

Boolean constants like yours can be used to choose between the disabler and the enabler, but there are neither if statements nor boolean template parameters in your code.

Defining supports_XYZ<must_have_XYZ<T> > makes very little sense if you don't actually instantiate any must_have_XYZ<> (e.g. must_have_XYZ<Pt>).

The concern about not knowing the class name is, I'm afraid, absurd: if you don't know what classes posterity will try to use with the templates you are writing now, you cannot tell what template specializations will be needed (and you aren't even certain you'll need to mess with overloading).

In the specific case of your example, it's both hard to imagine how constraints() might be adapted to fundamentally different point representations and easy to see that it should really operate on a decently explicit point interface.

I'm not too clear what you're saying so please bear with me if I've misinterpreted you.

I haven't included any if's since I haven't reached that point in development yet (I believe they're implicit anyway) I'm working towards that point but first need to define a traits class or something like a traits class which will evaluate to true or false dependent on the properites of the passed parameter. In this case, I want members x, y and z (hence the supports_XYZ trait). If they're not present an alternative template would be instantiated or a compiler error would be caused. I'm concerned about the classes properties not it's name.

The constraint is my (clearly flawed) attempt at something like a traits class.

It was my understanding that since must_have_XYZ<T> is inside template<typename T> struct supports_XYZ it would pick up T from there. Clearly, I'm wrong there, too.
Quote:
 If the template function referred to accessor methods for the three coordinates you could make simple and efficient adapters for different point-like classes rather than unnecessarily assuming that point-like classes have public fields x,y and z.

True, but I would've thought that public fields would be just as likely as accessors.

A5

##### Share on other sites
Quote:
 Original post by loufoqueNote it is better to use helper instead, as that is actually guaranteed to work and is much more useful since you can check the type of &U::x is what you want.

You're right that it's probably better to implement it using pointer-to-member template arguments, however I got the impression that the OP didn't know (or didn't want to specify) the type of the member in advance, in which case I don't think you can use this technique.

OP: I should also emphasise the point others have raised, which is that is this check really necessary for your use? If the only purpose is to prevent instantiation of a template if the type does not have x/y/z members (or getX/getY/getZ accessors), the compiler would do this for you by giving an error when you reference them. What exactly do you want to do with the bool value you get?

##### Share on other sites
Quote:
 Original post by d00fusOP: I should also emphasise the point others have raised, which is that is this check really necessary for your use? If the only purpose is to prevent instantiation of a template if the type does not have x/y/z members (or getX/getY/getZ accessors), the compiler would do this for you by giving an error when you reference them. What exactly do you want to do with the bool value you get?
Whoa, I've been working on this for so long and moved so far from where I started I've almost forgotten...

I have several functions which read data from an input stream into a data structure, the data structure may be a sequence container (eg vector<int> or list<float>) or a point. So I want the code to select the correct functions to implement at compile time.

##### Share on other sites
Quote:
 Original post by d00fusAs far as I know there's no totally cross-platform way to do this (if so please correct me!). Something such as the following should detect the presence of a member "x" I believe on a compliant compiler:*** Source Snippet Removed ***To make this more useful, you'd probably want to define a macro that declares the has_member_foo struct for each member you want to test for, and probably another macro to wrap the test itself.Note that in general this is a tricky area as it depends on how the compiler treats sizeof expressions, which is by no means standard. See here for more info.

Looks like this method won't work with VS 2005 according to this article. I'll try it with 2008 when I get home tonight.

 fails in VS 2008, too, dang! Workaround, anyone?

A5

[Edited by - Amnesiac5 on June 9, 2009 4:23:54 PM]

1. 1
2. 2
3. 3
4. 4
Rutin
17
5. 5

• 11
• 32
• 12
• 12
• 11
• ### Forum Statistics

• Total Topics
631409
• Total Posts
2999928
×