基于类型存在的模板专用化
template specialization based on a type's existance
如果定义了某种类型,我想实现一些功能。问题是,如果类型不存在,编译器会将代码视为无效而拒绝。类似于基于模板的ifdef。这将在一个不知道其他代码包含什么的库中使用,如果还包括某些库,我想自动实现功能。也许这是错误的方法,但我想知道如果没有带有默认行为的ifdefs,是否可以做到这一点。
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头,并且是脆弱的(您冒着ptr
指向翻译单元之间不同的东西的风险)
以下是一些标准(来自N4140):
§3.4.3 (basic.lookup.qual)/1:
可以引用类或命名空间成员或枚举数的名称在
::
范围解析运算符应用于a之后嵌套名称说明符,表示其类、名称空间或枚举。如果一个::
范围解析运算符在嵌套名称说明符之前没有类型说明符,查找::只考虑名称空间、类型和特化为类型的模板。如果找到的名称不是指定名称空间或类、枚举或依赖类型
不幸的是,我认为在编译时没有简单的方法来确定类型是否定义,主要是由于c++预处理器的愚蠢。
此外,__has_include
不在当前的c++标准与,依靠#if __has_include (<boost/shared_ptr.hpp>)
不能解决你的问题,因为你不能说如果<boost/shared_ptr.hpp>
包含你的代码,那么你的编译器没有std::shared_ptr
。
3可能的解决方案:
-
如果您想使用boost处理较新的标准库,请考虑使用
<boost/config.hpp>
。例如,BOOST_NO_CXX11_SMART_PTR
宏将帮助确定std库是否有shared_ptr -
你可以实现自己的宏来检查编译器是否支持某些库,通过检查不同的编译器版本。然而,由于编译器的选项,这并不是一件容易的事。(例如gcc的
-std=c++03
vs-std=c++11
) -
你的工具链可能可以检查你的编译器的特性,并通过宏传递给编译器。看看是否配置。对于autoconf, FindSharedPtr。
- .cpp和.h文件中的模板专用化声明
- C++模板来检查友元函数的存在
- 既然存在危险,为什么项目要使用-I include开关
- 调用专用模板时出错"no matching function for call to [...]"
- 我们可以访问一个不存在的联盟的成员吗
- 模板专用化(按容器):value_type
- C++:对不存在的命名空间使用命名空间指令
- C++quit()函数中可能存在作用域问题
- C++擦除(如果存在)
- g++ 说函数不存在,即使包含正确的标头
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 有了gcc,是否可以链接库,但前提是它存在
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 如何确定模板专用化是否存在
- MSVC 编译器实例化函数模板的默认定义,即使存在专用化
- 如何使用type_traits生成依赖于是否存在类专用化的代码?
- 类模板部分专用化的参数列表的限制中是否存在GCC 4.9.1(5.1)错误
- 如何创建只存在于特定模板专用化的函数
- 是否可以将模板专用化建立在方法签名中是否存在某个参数的基础上
- 基于类型存在的模板专用化