Jump to content
  • Advertisement
Sign in to follow this  
imi

compile-time test whether template class implements something

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, is there a way to test at compile time, whether the template parameter type implements some function (without forcing the type to provide a custom constant/typedef?) So that's my problem:
struct HasFoo
{
    void Foo() {}
};

struct NoFoo
{
};

template<class T>
struct ToFooOrNotToFoo
{
    void Bar()
    {
        //if (check_at_compile_time(exists T::Foo))
            T().Foo();
    }
};

void somewhere()
{
    ToFooOrNotToFoo<HasFoo>().Bar();  // calls HasFoo::Foo()
    ToFooOrNotToFoo<NoFoo>().Bar();   // doesn't compile, but should
}
I am looking for the code in the comment ;) (or some equivalent solution). I am aware of the following solution, which forces the template parameter to specify some constant. (Some kind of "least intrusive" solution)
struct HasFoo
{
    static const bool FOO_DEFINED = true;
    void Foo() {}
};

struct NoFoo
{
    static const bool FOO_DEFINED = false;
};

template<class T>
struct ToFooOrNotToFoo
{
	template<bool> struct B2T { static void FooOrNot() {} };
	template<> struct B2T<true> { static void FooOrNot() {T().Foo();} };
	static void Bar()
	{
		B2T<T::FOO_DEFINED>::FooOrNot();
	}
};
I am also aware, that the bool constant can be moved out of the template class into some traits-class. However, I would like a solution where nothing additional has to be done. Just either a function is implemented or not. I already read "Modern C++ Design" and looked at Loki to no avail. Maybe there is a solution with the new language constructs auto, decltype and varadic templates? Ciao, Imi. [Edited by - imi on February 13, 2010 5:20:27 AM]

Share this post


Link to post
Share on other sites
Advertisement
that is what concepts are used for.

unfortunately, since concepts have been kicked out of the c++0x standard, you will have to resort to boost's concept checking library for now. it is not perfect and may seem a little complicated at first, but altogether does a pretty decent job of implementing concept checking with the current c++ featureset.

Share this post


Link to post
Share on other sites
You can do it with SFINAE
struct HasFoo
{
void Foo() {}
};

struct NoFoo
{
};

template <class T>
struct ToFooOrNotToFoo
{
template <bool, class X> struct B2T { static void FooOrNot() {} };
template <class X> struct B2T<true, X> { static void FooOrNot() { X().Foo(); } };

template <void (T::*)()> struct Empty {};
template <class X> static char Helper(Empty<&X::Foo>*);
template <class X> static float Helper(...);

static void Bar()
{
B2T<sizeof(Helper<T>(0))==1, T>::FooOrNot();
}
};


int main()
{
ToFooOrNotToFoo<HasFoo>().Bar();
ToFooOrNotToFoo<NoFoo>().Bar();
}

Share this post


Link to post
Share on other sites
Here is one way of making a trait out of it:


// Fallback, will return char array of size 0
char (*check_for_foo(...))[0];

// Test case, will be only be valid overload for check_for_foo
// if T::Foo is resolved. sizeof(&T::Foo) will be the size of a
// member pointer (e.g. not 0)
//
// Cast is there to make sure Foo has correct parameters/return value
template<class T>
char (*check_for_foo(const T &t))[sizeof(static_cast<void (T::*)()>(&T::Foo))];

template<class T>
struct foo_traits {
// Dummy method to get a T without knowing
// how they are created
static const T & ct();
enum { hasit = sizeof(*check_for_foo(ct())) != 0 };
};


Try google for SFINAE (substitution-failure-is-not-an-error) for better explanations on how this work.


Share this post


Link to post
Share on other sites
Just for the record...

Quote:
Original post by bubu LV

B2T<sizeof(Helper<T>(0))==1, T>::FooOrNot();


This does only work if sizeof(char) == 1 != sizeof(float), right? (Which is practically everywhere :-) )

Share this post


Link to post
Share on other sites
The C standard mandates that sizeof(char) == 1. One might consider using char [2] to represent the "true" case, probably wrapped in a struct.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
The C standard mandates that sizeof(char) == 1. One might consider using char [2] to represent the "true" case, probably wrapped in a struct.


I usually use a reference-to-array-of-2-chars.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!