Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable functions inside templated class

Tags:

c++

templates

I'm trying to disable some functions inside a simple template class. The functions that should be removed depend on whether the template argument has certain typedefs.

The example boils down to this:

template<typename T>
struct Foo
{
  typename T::Nested foo() { return typename T::Nested(); }
  int bar() { return 1; }
};


struct NoNested
{
};

struct WithNested
{
  typedef int Nested;
};

int main()
{
  Foo<WithNested> fwn;
  fwn.foo();
  fwn.bar();

  Foo<NoNested> fnn;
  //fnn.foo();
  fnn.bar();
}

However this gives me a error: no type named ‘Nested’ in ‘struct NoNested’ style error on gcc and clang++ (mind you old versions of both).

Is there an easy way to remove foo when the typedef T::Nested does not exit? (Other than template specialization of the Foo<T> class, as in the real code I have this for about 5 functions with different typedefs.. which would result in 2^5 different specialization )

EDIT: Since there has been some asking for the motivation for wanting to do this: I'd like to create something like acompile time FSM for use in a DSL.

I'd like to be able to do this

struct StateA;
struct StateB;
struct StateC;

struct StateA
{
  typedef StateB AfterNext;
};

struct StateB
{
   typedef StateA AfterPrev;
   typedef StateC AfterNext;
};

struct StateC
{
   typedef StateB AfterPrev;
};

template<typename T>
struct FSM
{
   FSM<typename T::AfterNext> next() { return FSM<T::AfterNext>(); };
   FSM<typename T::AfterPrev> prev() { return FSM<T::AfterPrev>(); };
};

So that

FSM<StateA>().next().prev().next().next();

compiles, but

FSM<StateA>().next().prev().prev();

fails.

Note that in reality there would be more transition functions than this, the transition functions would actually do something, and the FSM would store some state.

UPDATE: I've created proper examples using the methods that have been given so far. The answers vary in complexity, and while visitors method is the one I'd probably end up using (as it is simplest), my solution (the most complicated) is the only one that actually removes the function.

like image 892
Michael Anderson Avatar asked Sep 14 '11 08:09

Michael Anderson


2 Answers

You can use class template specialization. If you have several functions, then you can move each function to a base class, and specialize each base class.

like image 153
Johan Råde Avatar answered Sep 30 '22 18:09

Johan Råde


Try making function foo template itself. It will compile only when called, so you will get the error only when you will try calling it with NoNested class.

like image 25
Werolik Avatar answered Sep 30 '22 17:09

Werolik