有没有一种方法可以使用宏检测可移植的标准 header?

Is there a way to detect portably that a standard header is included using macros?

我想与 boost::swap 等效,在我的环境中,标准 header 可以包含也可以不包含。取决于项目许可和其他内容。
我想让部分代码受防护检测器保护:

让我们考虑一个编译单元。
具体项目,afore-written 潜力包括:

#include <algorithm> // (or <utility> for C++11 projects)

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

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
  }
}

我简化了,因为我们在这里不讨论 ADL 技巧的细节,但它会包含在内。
此处仅供参考,与本题无关:
http://www.boost.org/doc/libs/1_57_0/boost/core/swap.hpp

所以这个问题是关于如何检测标准 header 包含 _ALGORITHM_ 守卫存在于 visual studio 提供 header,但我在 http://www.cplusplus.com/reference/algorithm/ 上没有读到它应该有任何我可以检查的宏。

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

您有一个选项可以使您的重载比其他选项"worse match"。然后,只有当它们不存在时才会选择您的版本:

#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);
}  

发生了什么:

当有两个候选函数模板特化时,编译器执行"Partial ordering of function templates"('03 14.5.5.2)。这将检查一个模板的函数模板参数是否可用于专门化另一个模板。

对于每个模板,我们将使用虚拟参数 T1T2,并使用这些类型创建虚拟参数列表:

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

// our swap argument list
( T2 &, typename ForceLessSpecialized<T2>::TYPE & )

使用来自 std::swap 的虚拟参数专门化我们的交换得到:

Deduction from First parameter:  T == T1
Deduction from Second parameter:  Non Deduced Context

推导的TT1,推导成功。

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

Deduction from First parameter:  T == T2
Deduction from Second parameter:  T == ForceLessSpecialized<T2>::TYPE

T的推导类型不相同,因此这被认为是推导失败。

因此,std::swap 的合成参数可以用于特化我们的模板,但是我们模板的合成参数不能用于特化std::swapstd::swap 被认为更专业,因此赢得了偏序。

C++17 带来了一个新特性,现在使这成为可能 是相关的。
https://en.cppreference.com/w/cpp/preprocessor/include

叫做__has_include
此处示例:#if __has_include(<algorithm>)

编辑:尽管它与问题的要求不同,它只是说明可达性。