有没有办法可移植地检测使用宏包含标准头?

v.o*_*dou 8 c++ utility

我希望boost::swap在我的环境中创建一个等效的标准头文件,或者不能包括在内.取决于项目许可和其他东西.
我想让部分代码受到保护检测器的保护:

我们考虑一个编译单元.
具体项目,上述潜力包括:

#include <algorithm> // (or <utility> for C++11 projects)
Run Code Online (Sandbox Code Playgroud)

稍后在我的交换实用程序头中包含的项目代码中:

namespace MyCompany
{
  template<class T1, class T2>
  void swap(T1& left, T2& right)
  {
     #ifdef _ALGORITHM_   // you get the idea.
       std::swap(left, right);
     #else
       // fallback impl
     #endif
  }
}
Run Code Online (Sandbox Code Playgroud)

我简化了,因为我们不是在讨论ADL技巧的细节,但它将被包括在内.
这里是我所谈论的参考,但这与这个问题无关:http:
//www.boost.org/doc/libs/1_57_0/boost/core/swap.hpp

所以这个问题是关于,如何检测标准头包含?在_ALGORITHM_后卫出现在Visual Studio中提供的头,但我无处阅读http://www.cplusplus.com/reference/algorithm/,它应该有,我可以检查任何宏.

(最后注意:这个问题有点偏向XY.我真正想要的是检测std::swap函数的存在,而不是标题.)

Ric*_*den 5

你有一个选择让你的超负荷比其他选择更"匹配".然后,只有当它们不存在时才会选择您的版本:

#if 0
#include <algorithm>
using std::swap;
#endif

template <typename T>
struct ForceLessSpecialized {
  typedef T TYPE;
};

template <typename T>
void swap (T &, typename ForceLessSpecialized<T>::TYPE &) {
}

void bar () {
  int i;
  swap (i, i);
}  
Run Code Online (Sandbox Code Playgroud)

发生了什么:

当有两个候选函数模板特化时,编译器执行"函数模板的部分排序"('03 14.5.5.2).这将检查是否可以使用一个模板的功能模板参数来专门化另一个模板.

对于每个模板,我们将使用伪参数T1,T2并使用以下类型创建伪参数列表:

// std::swap argument list
( T1 &  , T1 & )

// our swap argument list
( T2 &, typename ForceLessSpecialized<T2>::TYPE & )
Run Code Online (Sandbox Code Playgroud)

使用伪参数来专门化我们的交换std::swap给出:

Deduction from First parameter:  T == T1
Deduction from Second parameter:  Non Deduced Context
Run Code Online (Sandbox Code Playgroud)

推导出来TT1和扣除成功了.

专门std::swap为我们的交换使用伪参数给出:

Deduction from First parameter:  T == T2
Deduction from Second parameter:  T == ForceLessSpecialized<T2>::TYPE
Run Code Online (Sandbox Code Playgroud)

推导出的类型T并不相同,因此这被认为是演绎失败.

因此,合成的参数std::swap可用于专门化我们的模板,但我们模板的合成参数不能用于专门化std::swap. std::swap被视为更专业,所以赢得部分ordernig.