Skills Application of SFINAE

1. SFINAE skills

SFINAE, Substitution Failure Is Not An Error. This has been analyzed in the previous template metaprogramming, and will not be repeated here. This article only analyzes two similar implementation techniques to promote the application in actual engineering. One is from the Muduo library, and the other is implemented using the interface of the standard library.
Here is a tribute to Mr. Chen Shuo.

2. Examples in the Muduo library

First upload the source code:


#include <iostream>
namespace detail
{
    
    
// This doesn't detect inherited member functions!
// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
template<typename T>
struct has_no_destroy
{
    
    
  template <typename C> static char test(decltype(&C::no_destroy));
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;
};
}  // namespace detail
template <typename T>
 static void init(T t)
  {
    
    
    T* value_ = new T();
    if (!detail::has_no_destroy<T>::value)
    {
    
    
            std::cout<<"is ok"<<t<<std::endl;
      //::atexit(destroy);
    }
  }

int main()
{
    
    
    int num = 200;
    init<int>(num);
    return 0;
}

The test procedure is added here for convenience.
This code is a singleton control method in the muduo library, using the SFINAE technology mentioned earlier. The program is very simple. First look at the template class has_no_destroy. It has two overloads of the test template function (you can look up the information if you don’t understand function overloading), and a static constant value of Boolean type (in c++20, you can Consider inline). The value of this variable is judged to be char or int32_t by the return value of the two template functions of sizeof to determine whether it is true or false. That is to say, if decltype(&C::no_destroy) exists, that is, the C class contains the function no_destroy, then the template overload matching is successful, that is, the value of sizeof is its return value char (1==1 is established), otherwise it is int32_t (4==1 does not hold).
In fact, this technology has been repeatedly analyzed before, and the reason why it is brought up again here is only one purpose, to combine with the actual project, and to give you a deeper impression.

Three, the method after c++11

After c++11, the following method was mentioned earlier:

template<typename T>
auto len (T const&& t) -> decltype((void)(t.size()) , T::size_type)//也可以使用std::enable_if,修改一下表达式即可
{
    
    
    return t.size();
}

There are two problems here, one is (void)(t.size()), which is forced to be converted to void, in order to avoid other behavior possibilities caused by users overloading the comma operator (that is, to eliminate uncertainty). The other is the role of the comma expression. The last formula is the real expected return type, but there is a premise that the contents of all the previous comma expressions are valid, and if there is no size() function in t, it will compile fail.

In fact, if you reach c++20, you can directly use Concepts technology.

template<typename T>
concept func_ask = requires(T t)
{
    
    
    t.no_destroy();
};

On the whole, it is simpler and clearer.

Four. Summary

This article belongs to the chapter of learning the new by reviewing the past, and it will be more in-depth reflection if it is mutually confirmed with the previous articles. Then whether you can better master and apply these technologies opens a door, and it is all up to you in the future.

Guess you like

Origin blog.csdn.net/fpcc/article/details/132118435