添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

有两个SDK版本,A版本类Base有setScalingMode函数,B版本类Base无setScalingMode函数, 为了同时兼容两个SDK版本,共用一套代码,常见的是通过宏隔离,但版本众多时管理起来会很麻烦,若可先判断是否含有该函数,若有则调用,C++11新增特性解决了这一问题

//伪代码
// 如果支持setScalingMode
if(hassetScalingMode())
    //do something
    setScalingMode() 

SFINAE:Substitution Failure Is Not An Error

匹配失败不是错误。就是说,匹配重载的函数 / 类时如果匹配后会引发编译错误,这个函数 / 类就不会作为候选(不会报错)。这是一个 C++11 的新特性,也是 enable_if 最核心的原理,其作用是当我们在进行模板特化的时候,会去选择那个正确的模板

decltype 求表达式的类型

推导表达式的类型,但不会执行表达式

int i;
double t;
struct A { double x; };
const A* a = new A();
decltype(a) x1;  //x1 是 A*
decltype(i) x2;  //x2 是 int
decltype(a -> x) x3;  // x3 是 double

std::declval  返回一个类型的右值引用

不管是否有默认构造函数或该类型不可以创建对象。(可以用于抽象基类); 

判断是否含有某个函数

template<typename T>
bool CkHasSetScalingMode(decltype(std::declval<T>().setScalingMode(std::declval<int>())) *test = nullptr)
	return true;
template<typename T>
bool CkHasSetScalingMode(...)
	return false;
CkHasSetScalingMode<className>(nullptr)
template<typename T>struct hasSet
private:
    template<typename U> static auto Check(int) -> decltype(std::declval<U>().setScalingMode(std::declval<int>()), std::true_type());
    template<typename U> static auto Check(...) -> decltype(std::false_type());
public:
static const bool value = std::is_same<decltype(Check<T>(0)), std::true_type>::value;
hasSet<className>::value 

函数存在则执行

template<typename T>
int b2hGbp(...) {
	cout << "not support setScalingMode" << endl;
	return -1;
template <typename T, void (T::*)(int mode) = &T::setScalingMode>
int b2hGbp(T *t, int mode) {
    t->setScalingMode(mode);
	return 0;
//该方案需先识别是含有该函数
/*template<typename T>
int b2hGbp(typename std::enable_if<hasSet<T>::value, T>::type *t, int mode) {
	cout << "b2hGbp 2.---------------------" << endl;
    t->setScalingMode(mode);
	return 0;

std::enable_if 

定义如下,只有第一个参数为true时才会定义type,enable_if<true, T>::type 即为 T,而 enable_if<false, T>::type 会引发编译错误

  // Primary template.
  /// Define a member typedef @c type only if a boolean constant is true.
  template<bool, typename _Tp = void>
    struct enable_if
  // Partial specialization for true.
  template<typename _Tp>
    struct enable_if<true, _Tp>
    { typedef _Tp type; };

参考文档:

https://blog.csdn.net/zhx6044/article/details/47295327

SFINAE https://blog.csdn.net/zjq2008wd/article/details/58180334

https://www.jianshu.com/p/45a2410d4085

enable_if  https://blog.csdn.net/jeffasd/article/details/84667090

https://ouuan.github.io/post/c-11-enable-if-%E7%9A%84%E4%BD%BF%E7%94%A8/

最近工作中遇到这样一个需求:实现一个ToString函数型T转换到字符串,如果型T中含有同名方法ToString则直接调用。 这样一个ToString实现可以使用std::enable_if来做到,但是这里的难点在于如何判断型T中存在这样一个ToString方法,以便可以放入enable_if中做SFINAE。 检查是否存在特定成员 相同的问题在知乎上有人提出过,@孙明琦的答案提供了一个用于检测特定检测子U在型T下是否有效的检测器is_detected_v。其中用到了一个C++17的std::void_t,考虑到目前C++17还没得用,这个实现只作参考之用(事实上C++
C++模板中,SFINEA规则是指”Substitution failure is not an error“(匹配失败不是错误)。具体来说,就是当重载的模板参数展开时,如果展开导致一些型不匹配,编译器并不报错。 我们可以使用这个规则来判断是否存在某个成员函数,请看下面的实例: #include #include #include template struct has_member_
namespace detail { template <class Default, class AlwaysVoid, template <class...> class Op, class... Args> struct detector { using value_t = std::false_type; using type = Default; template & template<typename T, uint32_t (T::*)(uint32_t) const = &T::Func> static constexpr bool Check(T *) { return true; } static constexpr bool Check(...) { return false; }
可以使用静态成员变量来实现只调用一次的效果。静态成员变量是属于的,而不是属于某个对象的,因此在多次构造对象时只会被初始化一次。在构造函数中,可以使用静态成员变量的值来判断是否需要再次进行初始化。如果静态成员变量已经被初始化过,那么就不需要再次进行初始化。例如,下面的代码中,使用了一个静态成员变量来控制只调用一次的效果: ```c++ class MyClass { public: MyClass() { if (!initialized) { // 只在第一次构造对象时执行以下代码 // ... initialized = true; private: static bool initialized; bool MyClass::initialized = false; python3启动失败 Fatal Python error: initfsencoding: unable to load the file system codec qq_38174332: 有的电脑可能是亿赛通没登录 python3启动失败 Fatal Python error: initfsencoding: unable to load the file system codec weixin_40895135: 好像是路径错误 ubuntu 20.04 安装配置Samba服务,Windows 和 linux协同工作 添加的用户需要在系统账号中存在———这句话很重要