让c++编译器显示一个类型可以转换成什么类型
Getting the C++ compiler to reveal what a type can be converted to
下面是一个有缺陷的(和简化的)模板函数,它期望在一个模板参数上工作,该参数可以转换为预定义数量的类型之一。
碰巧是两种类型,但可能更多。
void do_something_type_specific( const int &unused ) { std::cout << 'i'; }
void do_something_type_specific( const std::string &unused ) { std::cout << 's'; }
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
do_something_type_specific( *begin );
// Perhaps more code...
}
这恰好在我的环境中产生了期望的结果。如果*Iterator
生成的类型恰好可以转换为其中一个选项,则模板实例将成功编译。
然而,这段代码不必要地要求执行转换,尽管unused
未使用,但当begin == end
时仍然存在UB。
如何在c++ 03中实现这个行为而不出现这些问题?
在begin == end
时,您可以尝试使用std::iterator_traits<>而不是解引用导致未定义行为的迭代器。例如:
#include <iterator>
#include <string>
#include <cstdio>
void do_something_type_specific(std::string const&) { printf("%sn", __PRETTY_FUNCTION__); }
void do_something_type_specific(int const&) { printf("%sn", __PRETTY_FUNCTION__); }
template<class T>
struct ProduceValue
{
static T value;
};
template<class T>
T ProduceValue<T>::value;
// Specializations for types that can't be default constructed or must be initialized.
template<>
char* ProduceValue<char*>::value = "";
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific(ProduceValue<value_type>::value);
}
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
输出:void do_something_type_specific(const string&)
void do_something_type_specific(const int&)
唯一的不便之处在于ProduceValue<T>
必须专门化用于不能默认构造或由于其他原因必须初始化的类型(如char*
)。
您可以使用boost::is_convertible
元函数来确定类型T是否可以转换为其他类型u
其次,对于begin == end
,只需插入运行时检查。
问题中的问题代码试图利用模板参数和函数参数的特性。
函数形参允许类型转换,但需要类型的实例化。模板形参不需要实例化,但也不需要执行类型转换。
下面的模式使用Boost的enable_if
和is_convertible
来允许编译器选择模板函数,就好像模板参数支持与函数参数相同的类型转换规则一样。(感谢@dhavenith的建议)
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
// enable_if_c makes the return type either void or a Substitution Failure.
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,int>::value>::type
do_something_type_specific()
{
std::cout << 'i';
}
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,std::string>::value>::type
do_something_type_specific()
{
std::cout << 's';
}
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
// This code is from @MaximYegorushkin's answer. Vote him up :)
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific<value_type>();
// Perhaps more code...
}
这已经通过@MaximYegorushkin的示例main进行了验证。
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
输出:si
您可能想要这样做:
template <typename T>
void do_something_type_specific() {}
template <>
void do_something_type_specific<int>() {...}
template <typename Iterator>
void perform_work_on_a_range(Iterator begin, Iterator end) {
do_something_type_specific<typename Iterator::value_type>();
}
相关文章:
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 事件系统:使用类型转换或联合进行继承
- 如何在参数中定义隐式类型转换的构造函数?
- 类模板实例化中的类型转换