Enable_if template method specialization

I have the following code that does not compile. These are two functions in the template class that take arguments.

typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { // ... } typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { // .... } 

I want to have specialization in a member method depending on the type of Ret.

Somebody knows?

+6
source share
2 answers

SFINAE does not work with functions without a template (member or non-member).

As Kerrek SB points out, creating their non-member function templates will work. Or, as Xeo points out, creating member function templates with a default template argument will also work.

However, this only works because the two conditions std::enable_if do not overlap . If you want to add another overload for int (say), you will find that it does not scale as well. Depending on what you want to do, tag dispatching usually scales better than SFINAE with a few alternatives you want to send:

 #include<type_traits> template<typename Ret> class Foo { public: void _on_dispatched() { // tag dispachting: create dummy of either std::false_type or std::true_type // almost guaranteed to be optimized away by a decent compiler helper_on_dispatched(std::is_void<Ret>()); } private: void helper_on_dispatched(std::false_type) { // do stuff for non-void } void helper_on_dispatched(std::true_type) { // do stuff for void } }; int main() { Foo<void>()._on_dispatched(); Foo<int>()._on_dispatched(); return 0; } 
+7
source

SFINAE only works with templates. Your code can be made for compilation with a slight modification:

 template <typename Ret> typename std::enable_if<std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } template <typename Ret> typename std::enable_if<!std::is_void<Ret>::value, Ret>::type _on_dispatched() { /*...*/ } 

Using:

 auto q = _on_dispatched<int>(); 

You can, of course, not output the return type of the function, since it is not invertible. However, you can pack this template into another template:

 template <typename T> struct Foo { // insert templates here, maybe privately so T bar() { return _on_dispatched<T>(); } }; 
+3
source

Source: https://habr.com/ru/post/923104/


All Articles