如果定义了某种类型,我想实现一些功能。问题是如果类型不存在,编译器会拒绝代码为无效。类似于基于模板的 ifdef。这将在不知道其他代码包含什么的库中使用,如果还包含某些库,我想自动实现功能。也许这是错误的方法,但我想知道是否可以在没有默认行为的 ifdef 的情况下完成此操作。
template <typename=std::enable_if<type_exists<some_type>>::type>
void function() {
// code using some_type
}
template <>
void function() {
// code using other_type
}
如果 some_type 存在,此代码将选择第一个函数,如果 some_type 未定义,则选择第二个函数。该代码假定 other_type 存在。
另一个用例是这样的。
template <typename T, typename=std::enable_if<type_exists<boost::shared_ptr<T>>>::type>
using ptr = boost::shared_ptr<T>;
template <typename T>
using ptr = std::shared_ptr<T>;
如果库的用户包含 boost,则更喜欢 boost 指针,否则退回到 std::shared_ptr。
最佳答案
如果您只想在可用时使用 Boost(或任何其他库),则必须使用预处理器。 C++17 带有一个方便的 __has_include
宏。您可以像下面这样使用它:
#if __has_inlcude <boost/shared_ptr.hpp>
#include <boost/shared_ptr.hpp>
template<typename T>
using ptr = boost::shared_ptr<T>;
#else
#include <memory>
template<typename T>
using ptr = std::shared_ptr<T>;
#end
您也可以使用 #if defined(BOOST_VERSION)
来支持旧的编译器,但这依赖于已经包含的特定 boost header 并且很脆弱(您冒着指向 ptr
的风险翻译单元之间的不同事物)
这里有一些标准(来自 N4140):
§3.4.3 [basic.lookup.qual]/1:
The name of a class or namespace member or enumerator can be referred to after the
::
scope resolution operator applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a::
scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed.
关于c++ - 基于类型存在的模板特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40188047/