Making auto_cast safe
Making auto_cast safe
GMan发布了一个美味的auto_cast
"运算符"代码,允许在c++中编写如下代码:
float f = 4.0f;
int i = auto_cast(f);
// instead of:
int j = static_cast<int>(f);
或者更明显的
T x = value;
typename nested_type<with, template_arguments>::type y = auto_cast(x);
// instead of
typedef typename nested_type<with, template_arguments>::type my_type;
my_type z = static_cast<my_type>(x);
基本上,操作员可以很好地从static_cast
中去除不必要的冗余,同时仍然是安全的。它甚至比static_cast
更安全,因为它可以防止意外的类型不匹配:
int i = 1234;
short s = static_cast<char>(i); // s == -46, not 1234!
然而,j_random_hacker注意到了操作符中的一个缺陷:
static_cast允许向下转换,这可能是不安全的。
实际上,auto_cast
可能应该禁止向下转换,因为它们可能会失败:
class base { };
class derived : public base { };
base b;
derived* pd = auto_cast(&b); // should fail at compile time.
所以我的问题是:
如何修改auto_cast
实现以禁止向下转换?这可能涉及enable_if
。我特别感兴趣的是一种解决方案,它允许编译器在出现故障时提供良好的诊断(=可读的错误消息)。
看来您想使用T{u}
形式的初始化。
template <typename U>
operator U()
{
return U{std::forward<T>(mX)};
}
这些统一初始化的原因之一是,为了使用显式构造函数创建临时对象,您需要一个称为T(u)
的强制类型转换。T{u}
解决了这个问题。对于c++ 03,我想您可以这样做:
template<typename T>
struct construct_explicit {
template<typename U>
construct_explicit(U &u):t(u) { }
template<typename U>
construct_explicit(U const &u):t(u) { }
T &get() { return t; }
T const& get() const { return t; }
T t;
};
然后你可以说construct_explicit<U>(mX).get()
,尽管在转换函数中,它也可以使用命名变量作为中间步骤,我认为
template <typename U>
operator U()
{
// or C++03: U u(mX);
U u(std::forward<T>(mX));
return u;
}
如果T
是R
的基,则可以使用type-traits来禁用操作符。在c++ 0x中,可以显式地使用static_assert(std::is_base_of<T, U>::value, "Cannot auto_cast downwards!");
我甚至不会使用auto_cast,因为static_cast, const_cast, dynamic_cast和reinterpret_cast也被设计得很难看,以帮助指出可能需要重构的代码:一个难看的操作应该有一个难看的外观。
的第二个原因新式演员是c型演员在节目中很难被发现。例如,你不能方便地使用普通类型搜索强制转换编辑器或文字处理机。这几乎不可见的c风格强制转换尤其不幸的是都具有潜在的破坏性。一个丑陋的操作应该是丑陋的语法形式。这个观察结果是选择的部分原因是新样式强制转换的语法。一个进一步的原因是新的风格强制转换以匹配模板表示法;这样程序员就可以编写他们的自己的强制转换,特别是运行时检查投。
http://www2.research.att.com/~ bs/bs_faq2.html # static-cast
我更喜欢在代码中清楚地看到它可以更好的地方,或者我们明确地需要做这个丑陋的操作。
- 如何理解C++标准N3337中的expr.const.cast子句8
- C++Cast运算符过载
- C++长双大"safe"整数
- 有没有"safe" static_cast选择?
- 如何以" Safe "的方式获取 C++ 中的当前时间
- "thread-safe data"与"thread-safe code/functions"的区别
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- C++:"Expected '(' for function-style cast or type construction"错误
- 为什么选择 g++ 给予者:"error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]"
- Gtk+ g_signal_connect() 和 C++ lambda 会导致"invalid cast"错误
- Shared_ptr cast vs static_cast speed
- 是否有C++准则将第一个枚举设置为"safe"默认值?
- "Safe"将元素添加到 std::vector 的方法,超出了其 size() 但低于其容量 ()
- 在 iOS 上使用 Aruco 构建 OpenCV 时"Functional-style cast from id to double is not allowed"
- 覆盖 CAST 运算符(我认为它被称为向下转换)
- C++错误,隐 <function-style-cast> 式要求使用模板化类一次调用多个构造函数的多个转换
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- 有没有一种"safe"方法来声明 lippincott 函数,这样它就不会在捕获之外被调用?