Effective C++: SFINAE

case 1:

#include <iostream>
#include <typeinfo>
class Person{
 private:
  std::string str;
  
  class Get{
   private:
    int idx;
    
   public:
    using value_type = std::string;
    
    Get()=default;
    
    ~Get()=default;
    
    constexpr Get(const int& index):idx(index){};
    
    value_type operator()(const int& index) noexcept
    {
     return std::string("shihuawoaini");
    }
    
    operator value_type() noexcept
    {
     return (*this)(idx);
    }
  };
  
  
  public:
   Person()=default;
   
   template<typename T>
   explicit Person(T&& t);
   
   explicit Person(int idx);
   
   Person(const Person& p);
   
   Person(Person&& p);
   
   virtual ~Person()=default;
};
template<typename T>
Person::Person(T&& t)
       :str(std::forward<T>(t))
{
 std::cout<<"T-type"<<std::endl;
 std::cout<<typeid(t).name()<<std::endl;
 std::cout<<std::boolalpha<<std::is_same<const char (&)[13], T>::value<<std::endl;
}
Person::Person(int idx)
       :str(Get(idx))
{
 std::cout<<"-----------"<<std::endl;
}
Person::Person(const Person& p)
       :str(p.str)
{
 //
}
Person::Person(Person&& p)
       :str(std::move(p.str))
{
 
}
class SpecialPerson : public Person{
 private:
  std::string str_;
  
  public:
   SpecialPerson(const std::string& base, const std::string& inherit):Person(base),str_(inherit){}
   virtual ~SpecialPerson()=default;
   
   SpecialPerson(const SpecialPerson& sp)noexcept;
   SpecialPerson(SpecialPerson&& sp)noexcept;
   
   
};
SpecialPerson::SpecialPerson(const SpecialPerson& sp)noexcept
              :Person(sp),
               str_(sp.str_)
{
 //
}
SpecialPerson::SpecialPerson(SpecialPerson&& sp)noexcept
              :Person(sp),
               str_(std::move(sp.str_))
{
 //
}
int main()
{
 Person p1(std::string("shihuawoaini"));
 Person p2("shihuawoaini");
 
 //question 1:
 Person p3(2.5); //这里我们如果传入进去参数2.5,会调用模板构造函数,进而造成构造失败.
 //为什么呢?
 //因为2.5是double类型, 那么这么一来double类型转到int类型需要一次类型转换,而模板构造函数不需要转换
 //也就提供了更加精确的匹配. 
 
 //question 2:
 Person p3(p2); 这里调用了构造函数而不是拷贝构造函数.
 
 //question 3:
 SpecialPerson sp1(std::string("shihuawoani"), std::string("marry me"));
 SpecialPerson sp2(sp1);
 //这里会调用基类中的构造函数而不是基类中的拷贝构造函数!!!!!!!!
 //因为调用基类中的拷贝构造函数需要进行派生类向基类的转换.
 //而调用基类向派生类的转换是不需要的,因此匹配度更佳. 
 
 const Person p4("shihuawoaini");
 Person p5(p4);  //OK调用了拷贝构造函数. 
 Person p6(5); //OK调用了接受int的构造函数. 
 
 return 0;
}

 case 2:

#include <iostream>
class Person{
 private:
  std::string str;
  
  class Get{
   private:
    int idx;
    
    public:
     using value_type = std::string;
     
     constexpr Get(const int& index):idx(index){}
     
     value_type operator()(const int& index)noexcept
     {
      return std::string("shihuawoaini");
     }
     
     operator value_type()noexcept
     {
      return (*this)(idx);
     }
     
  };
  
  public:
   //注意这里的模板声明. 
   template<typename T, typename = typename std::enable_if< 
   !std::is_base_of<Person, typename std::decay<T>::type>::value
   &&
   !std::is_integral< typename std::remove_reference<T>::type >::value
   &&
   !std::is_same<double, typename std::decay<T>::type>::value
   &&
   !std::is_same<const char16_t*, typename std::decay<T>::type>::value //解决utf-8的问题. 
   >::type>
   Person(T&& t);
   
   Person(const int& index);
   
   Person(const Person& p);
   
   Person(Person&& p);
   
   virtual ~Person()=default;
};
template<typename T, typename>
Person::Person(T&& t)
       :str(std::forward<T>(t))
{
 //
 std::cout<<"template"<<std::endl;
}
Person::Person(const int& index)
       :str(Get(index))
{
 //
 std::cout<<"number"<<std::endl;
}
Person::Person(const Person& p)
       :str(p.str)
{
 //
}
Person::Person(Person&& p)
       :str(std::move(p.str))
{
 //
}
class SpecialPerson : public Person{
 private:
  std::string str_;
  
  public:
   SpecialPerson(const std::string& base, const std::string& inherit):Person(base),str_(inherit){}
   
   virtual ~SpecialPerson()=default;
   
   SpecialPerson(const SpecialPerson& sp);
   
   SpecialPerson(SpecialPerson&& sp);
};
SpecialPerson::SpecialPerson(const SpecialPerson& sp)
              :Person(sp),
               str_(sp.str_)
{
 //
}
SpecialPerson::SpecialPerson(SpecialPerson&& sp)
              :Person(sp),
               str_(std::move(sp.str_))
{
 //
}
int main()
{
 Person p1("shihuawoaini");
 Person p2(std::string("shihuawoaini"));
 //Person p(u"shihuawoaini"); //这里的 (u"shihuawoaini")是const char16_t[13]类型. std::string并没有构造函数结构这样的参数. 
 
 //qeustion 1: 
 Person p3(p2);
 
 //question 2: 
 Person p4(2);
 Person p5(3.14);
 
 //question 3:
 SpecialPerson sp1(std::string("shihua"), std::string("MarryMe"));
 SpecialPerson sp2(sp1);
 
 return 0;
}

16/5/2:

标签分配 

 #include <iostream>
#include <type_traits>
template<typename T>
void logAndAddImpl(T&& name, std::true_type)
{
 std::cout<<"true_type"<<std::endl;
}
template<typename T>
void logAndAddImpl(T&& name, std::false_type)
{
 std::cout<<"false_type"<<std::endl;
}
template<typename T>
void logAndAdd(T&& name)
{
 logAndAddImpl( std::forward<T>(name), std::is_integral< typename std::remove_reference<T>::type>()); //注意这里.
 //上面用的是std::is_integral<typename std::remove_reference<T>::type>());
 //而不是std::is_integral<typename std::remove_reference<T>::type>::value)
}
int main()
{
 std::string str("shihuawoaini");
 logAndAdd(str);
 
 logAndAdd(10);
 return 0;
}

 

你可能感兴趣的:(Effective C++: SFINAE)