有没有一种方法可以使用宏检测可移植的标准 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)。这将检查一个模板的函数模板参数是否可用于专门化另一个模板。
对于每个模板,我们将使用虚拟参数 T1
和 T2
,并使用这些类型创建虚拟参数列表:
// 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
推导的T
为T1
,推导成功。
使用我们的交换的虚拟参数专门化 std::swap
给出:
Deduction from First parameter: T == T2
Deduction from Second parameter: T == ForceLessSpecialized<T2>::TYPE
T
的推导类型不相同,因此这被认为是推导失败。
因此,std::swap
的合成参数可以用于特化我们的模板,但是我们模板的合成参数不能用于特化std::swap
。 std::swap
被认为更专业,因此赢得了偏序。
C++17 带来了一个新特性,现在使这成为可能 是相关的。
https://en.cppreference.com/w/cpp/preprocessor/include
叫做__has_include
此处示例:#if __has_include(<algorithm>)
编辑:尽管它与问题的要求不同,它只是说明可达性。
我想与 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)。这将检查一个模板的函数模板参数是否可用于专门化另一个模板。
对于每个模板,我们将使用虚拟参数 T1
和 T2
,并使用这些类型创建虚拟参数列表:
// 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
推导的T
为T1
,推导成功。
使用我们的交换的虚拟参数专门化 std::swap
给出:
Deduction from First parameter: T == T2
Deduction from Second parameter: T == ForceLessSpecialized<T2>::TYPE
T
的推导类型不相同,因此这被认为是推导失败。
因此,std::swap
的合成参数可以用于特化我们的模板,但是我们模板的合成参数不能用于特化std::swap
。 std::swap
被认为更专业,因此赢得了偏序。
C++17 带来了一个新特性,现在使这成为可能 是相关的。
https://en.cppreference.com/w/cpp/preprocessor/include
叫做__has_include
此处示例:#if __has_include(<algorithm>)
编辑:尽管它与问题的要求不同,它只是说明可达性。