#include <iostream>
using namespace std;
template<bool enable, typename T>
struct foo;
template<typename T>
struct foo<false , T>
{
//nothing
};
template<typename T>
struct foo<true , T>
{
void say_hello()
{
cout << "Hello !" << endl;
}
protected:
int m_some_data_when_I_enabled{};
};
template<bool Enable, typename T>
struct bar
:
foo<Enable , T>
{
//And there are lots of functions and members
//Here I need conditional 'using'
using foo<Enable , T>::say_hello;
void say_hello(int different_signature)
{
}
};
struct duck { };
int main(int, char**) {
bar<true , duck> enabled_bar;
bar<false , duck> disabled_bar;
}
It gives an error when I declare bar. It makes sense to me. So I need something like :
template<typename = typename std::enable_if<Enable>::type>
using foo<Enable , T>::say_hello();
I know I can solve the problem with specializing 'bar' but It has some members and in that case I would duplicate lots of codes. Is there a different, maybe tricky, way ?
You can declare a deleted say_hello in your 1st foo which makes the using statement in bar legal.
template<typename T>
struct foo<false , T>
{
void say_hello() = delete;
};
Here is the full example.
You can add a simple forwarding overload, and use SFINAE to conditionally disable it when the member does not exist in the base class. Like this:
template<typename V = T, typename = decltype(&foo<Enable, V>::say_hello)>
void say_hello()
{
bar::foo::say_hello();
}
See it Live
We need to use &foo<Enable, V>::say_hello instead of &foo<Enable, T>::say_hello to delay the check and make it happen during substitution (when an attempt is made to call the function) as opposed to it happening when bar is instantiated.
If the member doesn't exist, overload resolution will discard the new overload (on account of an ill-formed substitution), as though it never existed.
But it's worth noting that this won't work for overload sets (because one cannot take a pointer-to-member of an overload set). It will only work if you know there is only a single overload, which can have its pointer-to-member formed unambiguously.
Related
Let's suppose to have a templateclass Foo:
template <typename T>
class Foo {
void foo();
};
I have another template class Bar (independent from the first one):
template <int N>
class Bar {};
Let's say, I want to specialise the foo() method for whatever Bar class.
I'd wrongly write:
template <>
template <int N>
void Foo<Bar<N> >::foo() { /* ... */ }
The compiler blames me for because the type is not complete:
error: invalid use of incomplete type 'class Foo<Bar<N> >'
void Foo<Bar<N> >::foo() { }
Code
I am using C++98, but I'd like to know if there exist different solutions in C++11.
Note
I could solve the problem specialising the entire class Foo for a generic Bar, but after I should have to define all methods.
Example Code
That's not what I want, I am looking for (if exists) more elegant solution (both C++98 and C++11) which allows me to specialise and implement only a single class method.
EDIT:
The question on SO does not explain how to specialise with a template argument. Indeed, my question shows how the compiler complains about that.
For C++11 you can SFINAE enable/disable (using std::enable_if) two differents versions of foo() inside a not specialized Foo class.
In C++98 you don't have std::enable_if but you can simulate it (give me some minutes and I try to propose an example). Sorry: my idea doesn't works because this method require the use of default template arguments for methods that is a C++11 innovation.
Another way is define a template base class for Foo(), say FooBase, insert foo() (and only foo()) in FooBase and specialize FooBase.
Another way, that works also with C++98, can be tag dispatching: you can define an unique foo(), with zero parameter, that call another foo(), with a parameter that is determined by T.
The following is a full (C++98 compilable) example
#include <iostream>
struct barWay {};
struct noBarWay {};
template <int>
struct Bar
{ };
template <typename>
struct selectType
{ typedef noBarWay type; };
template <int N>
struct selectType< Bar<N> >
{ typedef barWay type; };
template <typename T>
struct Foo
{
void foo (noBarWay const &)
{ std::cout << "not Bar version" << std::endl; }
void foo (barWay const &)
{ std::cout << "Bar version" << std::endl; }
void foo ()
{ foo(typename selectType<T>::type()); }
};
int main ()
{
Foo<int> fi;
Foo< Bar<42> > fb;
fi.foo();
fb.foo();
}
if a common base is not desirable, yet another way could be giving foo() a customization point, like a trait for example:
template <typename T>
struct foo_traits;
template <typename T>
struct Foo {
void foo(){ foo_traits<T>::foo_cp(*this); }
};
template <typename T>
struct foo_traits{ static void foo_cp(T&){/*default*/} };
template <int N>
class Bar {};
template <int N>
struct foo_traits<Bar<N>>{ static void foo_cp(Foo<Bar<N>>&){/*spec*/} };
such trait could also be an implementation detail friend, if its only purpose is to internally provide a foo() specialization for Bar's.
If you cannot specialize foo, define it so that it delegates the call to an internal foo-implementation class. Then specialize that class.
Something like this should compile in C++98 and it doesn't differ much from your original code:
template <typename T>
class Foo {
template<typename>
struct FooImpl;
public:
void foo() { FooImpl<T>()(); }
};
template <int N>
class Bar {};
template <typename T>
template <int N>
struct Foo<T>::FooImpl< Bar<N> > {
void operator()() { /* ... */ }
};
int main() {
Foo< Bar<0> > fb;
fb.foo();
Foo<int> fi;
//fi.foo();
}
The last line doesn't compile as expected (at least I got it was the expected result, just define the function call operator for FooImpl otherwise).
This way you can define selectively the specializations for which you want foo to work. In all the other cases, an attempt at using foo will result in a compilation error.
I'd like to know if there exist different solutions in C++11.
This is a classic use case for tagged dispatch, of which max66 already suggested. The approach, and even syntax, are basically the same in C++98 and C++11.
Here's a bit of a cleaner implementation than max66's, I believe (running on godbolt):
template <class T>
class Foo {
template <class>
struct tag{};
template<class U>
void foo_helper(tag<U>){std::cout << "default\n";}
void foo_helper(tag<Bar<3> >){std::cout << "specialization for Bar<3>\n";}
public:
void foo(){return foo_helper(tag<T>());}
};
The principle is the same; a client function accepting no arguments calls a helper function that constructs an empty type based on the T argument. Then normal overloading takes care of the rest.
Only here I use a templated catch-all method.
In C++11 the syntax would only change slightly; We could say tag<Bar<3>> instead of tag<Bar<3> > because new parsing rules allow the chevron for nested templates.
We could also make the tag and the templated foo_helper catch-all into variadic templates to be a little more generic:
template <class T>
class Foo {
template <class...>
struct tag{};
template<class... U>
void foo_helper(tag<U...>){std::cout << "default\n";}
void foo_helper(tag<Bar<3>>){std::cout << "specialization for Bar<3>\n";}
public:
void foo(){return foo_helper(tag<T>{});}
};
Things actually start getting pretty interesting in C++17 with the introduction of constexpr if that allows us to write what looks like normal branching logic based on T (Live Demo):
template <class T>
class Foo {
public:
void foo(){
if constexpr (std::is_same_v<T, Bar<3>>){std::cout << "Specialization for Bar<3>\n";}
else std::cout << "default\n";
}
};
As you can see, all the tag stuff goes away in favor of using a simple if statement.
We take advantage of type_traits introduced in C++11 to check the type of T against our desired type. Something like this wouldn't necessarily work previously because all branches needed to be compiled. In C++17, only the branch that is selected (at compile-time) is compiled.
Note that you could emulate this behavior as early as C++98 by using typeid (godbolt demo):
void foo(){
if (typeid(T) == typeid(Bar<3>)){std::cout << "Specialization for Bar<3>\n";}
else std::cout << "default\n";
}
However, the typeid approach is a poor choice for 2 reasons:
It's a run time check (slow) for information we know at compile-time
It's brittle because all branches must compile for all template instantiations, whereas in C++17 if constexpr only compiles the branch that is selected.
enum class enabler{};
template<typename T>
class X {
template<typename std::enable_if<std::is_class<T>::value,enabler>::type = enabler()>
void func();
void func(int a);
void func(std::string b);
};
I have this class with these 3 overloads for func. I need the second/third versions to be available for both class/non-class types, and the first version to be available only for class types. when I tried to use enable_if as above, the class instantiation for non-class types gives compile error.
For SFINAE to work, the template argument must be deduced. In your case, T is already known by the time you attempt to instantiate func, so if the enable_if condition is false, instead of SFINAE, you get a hard error.
To fix the error, just add a template parameter whose default value is T, and use this new parameter in the enable_if check. Now deduction occurs and SFINAE can kick in for non-class types.
template<typename U = T,
typename std::enable_if<std::is_class<U>::value,enabler>::type = enabler()>
void func();
And you don't really need a dedicated enabler type either, this works too
template<typename U = T,
typename std::enable_if<std::is_class<U>::value, int>::type* = nullptr>
void func();
I'm not really sure what you're going for with enabler here, but you can't do what you're trying because the declaration for your member function must be valid since T is not deduced by func. To achieve what you want in adding an extra overload, you can use some moderately contrived inheritance.
struct XBaseImpl {
// whatever you want in both versions
void func(int a) { }
void func(std::string b) { }
};
template <typename, bool> struct XBase;
// is_class is true, contains the extra overload you want
template <typename T>
struct XBase<T, true> : XBaseImpl {
static_assert(std::is_class<T>{}, ""); // just to be safe
using XBaseImpl::func;
void func() { } // class-only
};
// is_class is false
template <typename T>
struct XBase<T, false> : XBaseImpl { };
template<typename T>
class X : public XBase<T, std::is_class<T>{}> { };
You are not enabling or disabling something.
You simply want a compile time error in one specific case.
Because of that you don't require to rely on sfinae, a static_assert is enough.
As a minimal, working example:
#include<string>
template<typename T>
class X {
public:
void func() {
static_assert(std::is_class<T>::value, "!");
// do whatever you want here
}
void func(int a) {}
void func(std::string b) {}
};
int main() {
X<int> x1;
X<std::string> x2;
x2.func(42);
x2.func();
x1.func(42);
// compilation error
// x1.func();
}
Once a SO user said me: this is not sfinae, this is - substitution failure is always an error - and in this case you should use a static_assert instead.
He was right, as shown in the above example a static_assert is easier to write and to understand than sfinae and does its work as well.
I am trying to do the following: a templated class should provide some functions dependend on whether or not the type it has been templated with contains a member variable with a given name. As example the following pseudocode which should provide "printid()" only when templated struct/class has a member called "id":
#include <iostream>
#include <type_traits>
struct A { int id; };
struct B { };
template<typename T>
class foo
{
T myvar;
public:
#if exists T.id (or the alternative: #if exists myvar.id)
printid() { std::cout << "I have element id."; }
#endif
};
int main(){
foo<A> ok;
ok.printid(); // should compile and execute
foo<B> nok;
nok.printid(); // should not compile
return 0;
}
Digging around SFINAE, traits, std::enable_if and StackOverflow, I think it can be done ... somehow. But I somehow fail to combine enable_if with the the following snippet from the question How to detect whether there is a specific member variable in class?:
template<typename T, typename = void>
struct has_id : std::false_type { };
template<typename T>
struct has_id<T, decltype(std::declval<T>().id, void())> : std::true_type { };
Any help appreciated.
Yep, it's possible. Here's an example:
template<typename T>
class foo
{
T myvar;
public:
template <class _T = T,
class = typename std::enable_if<
!std::is_function<decltype(_T::id)>::value>
::type>
void printid() { std::cout << "I have element id."; }
};
Specifically, note how we're "taking in" T as _T in order to not force a constraint on the class template parameter (which would make the class itself un-compileable). Instead, we're creating a new, independent template member function, which doesn't force anything on T itself—it just "happens to" use it as a default argument. That's the key part.
In C++, say that I have some class mom. I know that I can make a template function that accepts any class, like:
template <class T> void Iacceptanything(T x)
{
// Do something
}
Now, this works nice, but I would like to make a more restrict template class, something that accepts as T any type that inherits from class mom. I thought about making the function accept mom as only argument type, but in that function I need to do build a template object with the argument, therefore I need its type to be preserved (i.e., my object shouldn't be "pruned down" to only its being an heir of mom).
What I would need is something like:
template <class T:mom> void Iacceptonlysonsofmom(T x)
{
// Do something
}
Is this possible at all?
Use std::enable_if and std::is_base_of.
#include <type_traits>
#include <iostream>
class Base { };
class Derived : public Base { };
class NotDerived { };
// If the return type of foo() is not void, add where indicated.
template <typename T>
typename std::enable_if<std::is_base_of<Base, T>::value /*, some_type*/>::type
foo(T) {
std::cout << "Derived from Base." << std::endl;
}
// If the return type of foo() is not void, add where indicated.
template <typename T>
typename std::enable_if<!std::is_base_of<Base, T>::value /*, some_type*/>::type
foo(T) {
std::cout << "Not derived from Base." << std::endl;
}
int
main() {
Derived d;
NotDerived nd;
foo(d);
foo(nd);
}
Use std::enable_if and std::is_base_of like this:
template <typename T, typename = enable_if<is_base_of<mom, T>::value>::type>
void Iacceptonlysonsofmom(T x)
{
}
If you cannot use C++11, you can achieve the same using Boost's enable_if_c and is_base_of. In the above code, you will need to replace enable_if with enable_if_c and ensure that you use the appropriate namespaces.
As others have suggested you can use enable_if and SFINAE (Substition Failure Is Not An Error) but it can be problematic. It can be fragile across compilers, may cause problems with ODR if not done properly, can cause conflicts with functions pulled in from other scopes (ADL), and may not be the best option.
You do have a couple of alternative options which are less fickle and may make your code easier to understand and maintain. One option (as mentioned in comments) is to use static_assert and is_base_of. This is by far (IMHO) the easiest solution for what you are trying to accomplish. This approach allows you to maintain a single implementation of the function and force a compile time failure if the type is not the base Mom or derived from it.
#include <type_traits>
struct Mom { };
struct Child : Mom { };
struct Uncle { };
template <typename T>
void AcceptOnlyMomAndChildren(T)
{
static_assert(std::is_base_of<Mom, T>::value, "Not derived from Base.");
}
int main()
{
Child child;
Uncle uncle;
AcceptOnlyMomAndChildren(child);
AcceptOnlyMomAndChildren(uncle); // Fails
}
If you need to provide multiple functions that can handle types that are not derived from a particular base class using tag dispatching may make more sense. This is far less fickle across compilers and must easier on the eyes. It can also be easily expanded if you ever need to provide special handling for a type derived from mom (in your example).
#include <type_traits>
#include <iostream>
struct Mom { };
struct Child : Mom { };
struct Uncle { };
template <typename T>
void Func(T&, std::true_type)
{
std::cout << "Derived from Base." << std::endl;
}
template <typename T>
void Func(T&, std::false_type)
{
std::cout << "Not derived from Base." << std::endl;
}
template <typename T>
void Func(T& arg)
{
Func(
arg,
typename std::conditional<
std::is_base_of<Mom, T>::value,
std::true_type, std::false_type>::type());
}
int main()
{
Child child;
Uncle uncle;
Func(child);
Func(uncle);
}
In the above example std::conditional is used to specify the type of an additional argument determine which implementation of Func is called. You can substitute it with your own type traits scheme to support additional implementations if necessary.
I have a template class, say:
template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}
private:
T* foo_;
};
which I can instantiate with a bunch of different types T which support the onA and onB interface. I happen to have a case where two out of the several different types T I use needs a particular behavior controlled from someClient so I need to add some function doBar() to these two types (call them Edge1 and Edge2). Then I want a part of the someClient code to call foo_->doBar() but without breaking when the type of foo_ does not have that. Is there a way to use boost::enable_if to have a someClient::doBar() which will call foo_->doBar() only for those two types, but not be there, or expand to nothing if the types are not Edge1 or Edge2?
I was thinking along the lines of:
template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
You don't need to pull any special tricks at all if you just don't call member functions that don't make sense. Template member functions are only specialized when needed (unless you add an explicit specialization). So the following code works fine:
template <typename T> struct Foo
{
void do_foo() { p->foo(); }
void do_bar() { p->bar(); }
T * p;
};
struct A { void foo() {} };
int main()
{
A a;
Foo<A> x = { &a };
x.do_foo();
}
The fact that Foo<A>::do_bar wouldn't compile is not an issue, since the member function is never instantiated. And p->bar isn't a compiler error, because p has a dependent type and the line is thus only parsed in the second lookup phase (which never happens).
I think this does what you want. I used C++11 <type_traits> instead of boost's:
struct Edge {
void doBar() { std::cout << "did Bar."; }
};
template<typename T>
class someClient
{
public:
template<typename U = T>
typename
std::enable_if<std::is_same<U, Edge>::value, void>::type
doBar() { foo_->doBar(); }
template<typename U = T>
void doBar( typename std::enable_if<!std::is_same<U, Edge>::value, void>::type* = 0 )
{ /* do nothing */ }
private:
T* foo_;
};
int main()
{
someClient<int> i;
someClient<Edge> e;
i.doBar();
e.doBar(); // outputs "did Bar."
}
doBar() needs to be template itself for this to work, explanation here: std::enable_if to conditionally compile a member function