Disable functions inside templated class - c++

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.

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.

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.

You could add a nested typedef to every class, such that compilation only fails when the function is instantiated.
struct null_type; //an incomplete type, you could use a more descriptive name for your particular problem
template<typename T>
struct Foo
{
typename T::Nested foo() { return typename T::Nested(); }
int bar() { return 1; }
};
struct NoNested
{
typedef null_type Nested;
};
struct WithNested
{
typedef int Nested;
};
int main()
{
Foo<WithNested> fwn;
fwn.foo();
fwn.bar();
Foo<NoNested> fnn;
//fnn.foo(); //attempt to use incomplete type when used
fnn.bar();
}

It is possible to choose the type T::Nested, if it exists, otherwise void, as follows.
The default choice is void:
template<class T, class = void>
struct NestedReturn
{
typedef void type;
};
A template which always returns void, whatever type you give it:
template<class T>
struct Void
{
typedef void type;
};
A specialisation for types with a Nested nested class by SFINAE. Note that typename Void<typename T::Nested>::type is always void, to match the default second parameter of void in the base template:
template<class T>
struct NestedReturn<T, typename Void<typename T::Nested>::type>
{
typedef typename T::Nested type;
};
And now we use it. Note that foo() is not actually removed when there is no T::Nested, but instantiating it causes an error.
template<typename T>
struct Foo
{
typename NestedReturn<T>::type 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();
}
I suspect that using default function template parameters it would be possible to remove foo() properly using SFINAE, but that's only possible in C++11 (untested guesswork):
template<typename T>
struct Foo
{
template<class N = T::Nested>
N foo() { return N(); }
int bar() { return 1; }
};

Here's how I think I can solve it. It's inspired by user763305's comments.
It requires 2*N specialisations rather than 2^N.
template <typename T>
struct has_nested {
// Variables "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::Nested*);
template <typename>
static no& test(...);
// If the "sizeof" the result of calling test<T>(0) would be equal to the sizeof(yes),
// the first overload worked and T has a nested type named type.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template<typename T>
struct FooBase
{
int bar() { return 1; }
};
template<typename T, bool>
struct FooImpl : public FooBase<T>
{
};
template<typename T>
struct FooImpl<T,true> : public FooBase<T>
{
typename T::Nested foo() { return typename T::Nested(); }
};
template<typename T>
struct Foo : public FooImpl<T, has_nested<T>::value >
{
};
struct NoNested
{
};
struct WithNested
{
typedef int Nested;
};
int main()
{
Foo<WithNested> fwn;
fwn.foo();
fwn.bar();
Foo<NoNested> fnn;
//fnn.foo();
fnn.bar();
}

Related

Is there way to perform "if (condition) typedef ..."

I would like to perform a typedef, if and only if a compile-time condition is met. If the condition is not met, no typedef shall be performed at all.
Is that possible in C++11?
Example:
class A {
std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1".
std::conditional_typedef<false,int,myType2>; // Does nothing at all.
};
I am looking for this fictional std::conditional_typedef.
Another way can be passing from the specialization of a base class
// foo is a light struct (only a typedef or not at all) that can be
// developed in two versions
template <bool>
struct foo;
template <>
struct foo<true>
{ typedef int myType1; }; // or using myType1 = int;
template <>
struct foo<false>
{ };
template <bool B>
struct bar : public foo<B> // B can be a type_traits value derived
// from template arguments for bar
{
// potential complex struct or class, developed only one time
};
int main()
{
bar<true>::myType1 mt1 { 1 };
// bar<false>::myType1 mt2 { 1 }; error: ‘myType1’ is not a member of ‘bar<false>’
}
Unfortunately desired syntax can't be possible as names that are passed to the template instantiation have to be already defined. In your case myType1 and myType2 wouldn't name anything from compiler point of view. However if you're not insisting on the syntax you've mentioned you could try to use std::enable_if as follows:
#include <type_traits>
struct A {
struct myType1: std::enable_if<true, int> { }; //std::conditional_typedef<true,int,myType1>; // Performs "typedef int myType1".
struct myType2: std::enable_if<false, int> { }; //std::conditional_typedef<false,int,myType2>; // Does nothing at all.
};
int main() {
A::myType1::type i;
//A::myType2::type i2; // causes error: no type named 'type' in 'A::myType2'
(void)i;
}
[live demo]
Edit:
Yet another way that came to my mind (utilizing using with default template parameter):
#include <type_traits>
struct A {
template <class T = int>
using myType1 = typename std::enable_if<true, T>::type;
template <class T = int>
using myType2 = typename std::enable_if<false, T>::type;
};
int main() {
A::myType1<> i;
//A::myType2<> j;
(void)i;
}
[live demo]
Similar to std::enable_if, you could have your class descend from a template that does your typedef if you want to use your own names and not have to do A::mytype1::type. The downside is that you'd have to descend from multiple structs if you want to do this a lot.
namespace impl {
template<bool, typename> struct A;
template<typename T> struct A<true, T>{ typedef T mytype1; };
template<typename T> struct A<false, T> {};
}
struct A : public impl::A<condition, int> {
//If condition is met, then ::mytype1 will be defined as a typedef int
};
int main() {
A::mytype1 i; //Will fail if condition wasn't met
}

Template partial specialisation not working with typedefs

In this example:
template<typename T>
struct ConditionalValue
{
typedef boost::optional<T> type;
};
template<typename T>
struct FindRootValueType
{
typedef typename T::root_type type;
};
template<typename T>
struct FindRootValueType<typename ConditionalValue<T>::type>
{
typedef typename ConditionalValue<T>::type type;
};
template<typename T>
struct Base
{
typedef T value_type;
typedef typename FindRootValueType<value_type>::type root_type;
std::vector<value_type> data;
};
template<typename T>
struct A : public Base<typename ConditionalValue<T>::type>
{
};
template<typename T>
struct B : public Base<A<T>>
{
};
template<typename T>
struct C : public Base<B<T>>
{
};
// C<int>::value_type == B<int>
// C<int>::data == std::vector<B<int>>
// C<int>::data ~= std::vector<std::vector<std::vector<boost::optional<int>>>>
// C<int>::root_type == boost::optional<int>
ConditionalValue is a template alias that simply tries to give an alternate name to boost::optional (such that something else can be used to replace it), and FindRootValueType is a metafunction intended to walk up a chain of types that have definitions similar to those shown at the bottom until it stops at the boost::optional, and then simply returns that.
However as written this does not work (at least not in VS2008). To fix it, the specialization of FindRootValueType must explicitly use boost::optional<T>, not the typedef that should be equivalent to it. (And this defeats the goal of only specifying the underlying implementation type in one place.)
Is this a compiler bug or is this supposed to not work? Or am I just doing something wrong? Is there a better way to write it such that it works as expected?
I also tried reversing the logic thusly:
template<typename T>
struct FindRootValueType
{
typedef T type;
};
// define Base here
template<typename T>
struct FindRootValueType<Base<T>>
{
typedef typename T::root_type type;
};
// define A here
template<typename T>
struct FindRootValueType<A<T>>
{
typedef T type;
};
// define B, C here (no specialisation)
But this doesn't work either (I think because specialisation doesn't follow base types, or possibly it's just the order of definition). I don't want to have to specialise for B, C etc specifically.
(BTW, in both of the above, "not working" means that compiler errors were produced that indicated that it was using the base definition of FindRootValueType, not the specialisation.)
Inspired by this answer to a related question link, I tried the following and it seemed to work:
template<typename T>
struct HasRootType
{
private:
typedef char no;
struct yes { no m[2]; };
static T* make();
template<typename U>
static yes check(U*, typename U::root_type* = 0);
static no check(...);
public:
static bool const value = sizeof(check(make())) == sizeof(yes);
};
template<typename T, bool = HasRootType<T>::value>
struct FindRootValueType
{
typedef typename T::root_type type;
};
template<typename T>
struct FindRootValueType<T, false>
{
typedef T type;
};
// define Base, A, B, C, etc here
Thus redefining the problem to "walk up the types until you find one without a root_type, then return that". I'm still curious why typedef-based specialisation didn't seem to work, though.

How to do one explicit specialization for multiple types?

Considering a template function like below how is it possible to do explicitly specialize one version of function for multiple types:
template <typename T>
void doSomething(){
//whatever
}
The intention is to have one specialization instead of multiple following ones because //something is the same:
void doSomething<int>(){
//something
}
void doSomething<float>(){
//something
}
void doSomething<double>(){
//something
}
any method to achieve one specialization?
You can't make template function specialization. But you could delegate the implementation in a helper class, that can be used from your function. Some skeleton code:
Implement a template class and specialize it:
template< typename T, bool isArithmetic>
struct Something { void operator()() { ... } };
template< typename T, true>
struct Something { void operator()() { ... do something specialized for arithmetic types; } }
Then use it in the template function:
template< typename T>
void myFunction()
{
Something<T, IsArithmetic<T>::value>()();
}
Where IsArithmetic is a class that provides the information about type T (selector). You can find such type info in boost libraries, for example.
You could just have a kind of doSomethingImpl function.
template<typename T> doSomethingImpl() {
// whatever
}
template<typename T> doSomething() {
// something else
}
template<> doSomething<float>() {
doSomethingImpl<float>();
}
template<> doSomething<int>() {
doSomethingImpl<int>();
}
It's also possible to specialize more generically, using SFINAE and std::is_numeric<T>, for example.
using c++ 2011 (option -std=c++11), this works well:
#include <iostream>
template <typename T>
struct unsignedObject
{
unsignedObject() {
std::cout << "instanciate a unsignedObject\n";
}
};
struct signedObject
{
signedObject() {
std::cout << "instanciate a signedObject\n";
}
};
template <typename T>
struct objectImpl
{
typedef unsignedObject<T> impl; // optional default implementation (the line can be removed)
};
template <> struct objectImpl<unsigned char> { typedef unsignedObject<unsigned char> impl; };
template <> struct objectImpl<unsigned int> { typedef unsignedObject<unsigned int> impl; };
template <> struct objectImpl<unsigned short> { typedef unsignedObject<unsigned short> impl; };
template <> struct objectImpl<double> { typedef signedObject impl; };
template <> struct objectImpl<int> { typedef signedObject impl; };
template <> struct objectImpl<short> { typedef signedObject impl; };
template <> struct objectImpl<char> { typedef signedObject impl; };
template <typename T>
using object = typename objectImpl<T>::impl;
int main(void)
{
object<int> x; // x is a signedObject.
object<double> y; // y is a signedObject.
object<unsigned short> z; // z is a unsignedObject.
return 0;
}

C++ syntax for explicit specialization of a template function in a template class?

I have code which works in VC9 (Microsoft Visual C++ 2008 SP1) but not in GCC 4.2 (on Mac):
struct tag {};
template< typename T >
struct C
{
template< typename Tag >
void f( T ); // declaration only
template<>
inline void f< tag >( T ) {} // ERROR: explicit specialization in
}; // non-namespace scope 'structC<T>'
I understand that GCC would like me to move my explicit specialization outside the class but I can't figure out the syntax. Any ideas?
// the following is not correct syntax, what is?
template< typename T >
template<>
inline void C< T >::f< tag >( T ) {}
You can't specialize a member function without explicitly specializing the containing class.
What you can do however is forward calls to a member function of a partially specialized type:
template<class T, class Tag>
struct helper {
static void f(T);
};
template<class T>
struct helper<T, tag1> {
static void f(T) {}
};
template<class T>
struct C {
// ...
template<class Tag>
void foo(T t) {
helper<T, Tag>::f(t);
}
};
GCC is in the clear, here. MSVC has a non-standard extension that allows in-class specialization. The standard, however, says:
14.7.3.2:
2. An explicit specialization shall be declared in the namespace of
which the template is a member, or, for member templates, in the
namespace of which the enclosing class or enclosing class template is
a member. An explicit specialization of a member function, member
class or static data member of a class template shall be declared in
the namespace of which the class template is a member.
Additionally, you can't partially specialize a function. (Though I'm unsure about the details in your case, that would be the final blow.)
You could do this:
#include <iostream>
struct true_type {};
struct false_type {};
template <typename T, typename U>
struct is_same : false_type
{
static const bool value = false;
};
template <typename T>
struct is_same<T, T> : true_type
{
static const bool value = true;
};
struct tag1 {};
struct tag2 {};
template< typename T >
struct C
{
typedef T t_type;
template< typename Tag >
void foo( t_type pX)
{
foo_detail( pX, is_same<Tag, tag1>() );
}
private:
void foo_detail( t_type, const true_type& )
{
std::cout << "In tag1 version." << std::endl;
}
void foo_detail( t_type, const false_type& )
{
std::cout << "In not tag1 version." << std::endl;
}
};
int main(void)
{
C<int> c;
c.foo<tag1>(int());
c.foo<tag2>(int());
c.foo<double>(int());
}
Though this is somewhat ugly.
Came across this question. This should work:
struct tag {};
template< typename T >
struct C {
template< typename Tag, typename std::enable_if<std::is_same<Tag, tag>::value, int>::type = 0>
void f( T ){
std::cout<<"tag type" <<std::endl;
}
template< typename Tag, typename std::enable_if<!std::is_same<Tag, tag>::value, int>::type = 0>
void f( T ){
std::cout<<"non tag type" <<std::endl;
}
};
I know this may not satisfy you, but I do not believe you may not have a specialization enclosed within a non-explicitly-specialized structure.
template<>
template<>
inline void C< tag1 >::foo< tag2 >( t_type ) {}
The basic detail is that you need to put the code declaration outside of the class so that there is only one declaration of it. If you leave it in a header, declared for all including c++ source files to see, you end up with multiple instances of the same class defined. Just put the declaration of the templated function in the header file, and then move the declared specializations of that templated function into your C++ source file and all will be good because the compiler will generate the correct references based on the types of specialization you use in your source code.
For example you want to create an extensible Number class like java's Number class so that you can pass numeric values around. If this is in the .h/.hpp file, the compiler will know how to generate references to each specialization because the return type is part of the generated function name that the compiler generates references for.
class Number {
Int32 intVal;
double d;
float f;
Int64 longVal;
std::string strVal;
public:
template<T>
T getValue();
... other functions needed go here...
};
In your C++ source file you can just write the following.
template<>
Int32 Number::getValue() { return intVal; }
template<>
double Number::getValue() { return d; }
template<>
float Number::getValue() { return f; }
template<>
Int64 Number::getValue() { return longVal; }
template<>
std::string Number::getValue() { return strVal; }
Now when you pass a Number around, depending on which value type you assign it to, you can use an appropriate value type on a getValue<>() calls.
From https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85282 (Patrick Palka)
[...] as a workaround, instead of e.g.:
struct A {
template<class T> struct B;
template<>
struct B<int> { }; // unsupported class-scope explicit specialization
};
in C++20 one can do:
struct A {
template<class T>
struct B;
template<std::same_as<int> T>
struct B<T> { };
};
or in C++17:
struct A {
template<class T, class = void>
struct B;
template<class T>
struct B<T, std::enable_if_t<std::is_same_v<int,T>>> { };
};
While the code is perhaps non-compliant, one practical solution is to switch to clang, where it works fine.
https://godbolt.org/z/hPbP1M
gcc doesn't allow member function full specialization inside a class.
This is because functionality wise it is the same as function overloading.
So just remove template<> from specializations and make them function overloads instead.
Try this:
template <> template<typename T> inline void C<T> :: foo<tag2>(T) {}

Template specialization based on inherit class

I want to make this specialized w/o changing main. Is it possible to specialize something based on its base class? I hope so.
-edit-
I'll have several classes that inherit from SomeTag. I don't want to write the same specialization for each of them.
class SomeTag {};
class InheritSomeTag : public SomeTag {};
template <class T, class Tag=T>
struct MyClass
{
};
template <class T>
struct MyClass<T, SomeTag>
{
typedef int isSpecialized;
};
int main()
{
MyClass<SomeTag>::isSpecialized test1; //ok
MyClass<InheritSomeTag>::isSpecialized test2; //how do i make this specialized w/o changing main()
return 0;
}
This article describes a neat trick: http://www.gotw.ca/publications/mxc++-item-4.htm
Here's the basic idea. You first need an IsDerivedFrom class (this provides runtime and compile-time checking):
template<typename D, typename B>
class IsDerivedFrom
{
class No { };
class Yes { No no[3]; };
static Yes Test( B* ); // not defined
static No Test( ... ); // not defined
static void Constraints(D* p) { B* pb = p; pb = p; }
public:
enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };
IsDerivedFrom() { void(*p)(D*) = Constraints; }
};
Then your MyClass needs an implementation that's potentially specialized:
template<typename T, int>
class MyClassImpl
{
// general case: T is not derived from SomeTag
};
template<typename T>
class MyClassImpl<T, 1>
{
// T is derived from SomeTag
public:
typedef int isSpecialized;
};
and MyClass actually looks like:
template<typename T>
class MyClass: public MyClassImpl<T, IsDerivedFrom<T, SomeTag>::Is>
{
};
Then your main will be fine the way it is:
int main()
{
MyClass<SomeTag>::isSpecialized test1; //ok
MyClass<InheritSomeTag>::isSpecialized test2; //ok also
return 0;
}
And the short version now, 2014, using C++-11:
#include <type_traits>
struct SomeTag { };
struct InheritSomeTag : SomeTag { };
template<typename T, bool = std::is_base_of<SomeTag, T>::value>
struct MyClass { };
template<typename T>
struct MyClass<T, true> {
typedef int isSpecialized;
};
int main() {
MyClass<SomeTag>::isSpecialized test1; /* ok */
MyClass<InheritSomeTag>::isSpecialized test2; /* ok */
}
Well, the article in the answer above appeared in February 2002. While it works, today we know there are better ways. Alternatively, you can use enable_if:
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
template<typename, typename>
struct is_same {
static bool const value = false;
};
template<typename A>
struct is_same<A, A> {
static bool const value = true;
};
template<typename B, typename D>
struct is_base_of {
static D * create_d();
static char (& chk(B *))[1];
static char (& chk(...))[2];
static bool const value = sizeof chk(create_d()) == 1 &&
!is_same<B volatile const,
void volatile const>::value;
};
struct SomeTag { };
struct InheritSomeTag : SomeTag { };
template<typename T, typename = void>
struct MyClass { /* T not derived from SomeTag */ };
template<typename T>
struct MyClass<T, typename enable_if<is_base_of<SomeTag, T>::value>::type> {
typedef int isSpecialized;
};
int main() {
MyClass<SomeTag>::isSpecialized test1; /* ok */
MyClass<InheritSomeTag>::isSpecialized test2; /* ok */
}
In your case, the only way that I see would be to explicitly specialize MyClass for InheritSomeTag. However, the SeqAn paper proposes a mechanism called “template sublassing” that does what you want – albeit with a different inheritance syntax, so the code isn't compatible with your current main function.
// Base class
template <typename TSpec = void>
class SomeTag { };
// Type tag, NOT part of the inheritance chain
template <typename TSpec = void>
struct InheritSomeTag { };
// Derived class, uses type tag
template <typename TSpec>
class SomeTag<InheritSomeTag<TSpec> > : public SomeTag<void> { };
template <class T, class Tag=T>
struct MyClass { };
template <class T, typename TSpec>
struct MyClass<T, SomeTag<TSpec> >
{
typedef int isSpecialized;
};
int main()
{
MyClass<SomeTag<> >::isSpecialized test1; //ok
MyClass<SomeTag<InheritSomeTag<> > >::isSpecialized test2; //ok
}
This certainly looks strange and is very cumbersome but it allows a true inheritance mechanism with polymorphic functions that is executed at compile time. If you want to see this in action, have a look at some SeqAn examples.
That being said, I believe that SeqAn is a special case and not many applications would profit from this extremely difficult syntax (deciphering SeqAn-related compiler errors is a real pain in the *ss!)
Using concepts and the requires keyword from C++20 is an even simpler and more expressive way to do this without having to introduce a redundant boolean non-type template parameter like in C++11:
// C++20:
#include <concepts>
#include <iostream>
struct SomeTag { };
struct InheritSomeTag : SomeTag { };
template<typename T>
struct MyClass
{
void Print()
{
std::cout << "Not derived from someTag\n";
}
};
// std::derived_from is a predefined concept already included in the STL
template<typename T>
requires std::derived_from<T, SomeTag>
struct MyClass<T>
{
void Print()
{
std::cout << "derived from someTag\n";
}
};
int main()
{
MyClass<InheritSomeTag> test1;
test1.Print(); // derived from someTag
MyClass<int> test2;
test2.Print(); // Not derived from someTag
// Note how even the base tag itself returns true from std::derived_from:
MyClass<SomeTag> test3;
test3.Print(); // derived from someTag
}