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

时间:2015-03-04 02:24:30

标签: c++ utility

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

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

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

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

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

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

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

2 个答案:

答案 0 :(得分: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);
}  

发生了什么:

当有两个候选函数模板特化时,编译器执行“函数模板的部分排序”('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被视为更加专业化,因此赢得了部分订单。

答案 1 :(得分:1)

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

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

编辑:它与问题的要求不同,只是告诉可及性。