GMan发布了一个美味的auto_cast"运算符"代码,允许在C++中编写如下代码:
float f = 4.0f;
int i = auto_cast(f);
// instead of:
int j = static_cast<int>(f);
Run Code Online (Sandbox Code Playgroud)
或者,更突出的是,
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);
Run Code Online (Sandbox Code Playgroud)
基本上,操作员可以很好地从a中删除不必要的冗余static_cast,同时仍然是安全的.它甚至比防止意外不匹配类型更安全static_cast:
int i = 1234;
short s = static_cast<char>(i); // s == -46, not 1234!
Run Code Online (Sandbox Code Playgroud)
但是,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.
Run Code Online (Sandbox Code Playgroud)
因此我的问题是:
您如何修改auto_cast实施以禁止向下转发?
这可能涉及到enable_if.我特别感兴趣的是一种解决方案,它允许编译器在出现故障时提供良好的诊断(=可读错误消息).
看来你想要使用T{u}初始化的形式.
template <typename U>
operator U()
{
return U{std::forward<T>(mX)};
}
Run Code Online (Sandbox Code Playgroud)
这些统一初始化的原因之一是要使用显式构造函数来创建临时,你需要一个演员名称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;
};
Run Code Online (Sandbox Code Playgroud)
然后你可以说construct_explicit<U>(mX).get(),虽然在你的转换函数中的情况下,它也可以使用命名变量作为中间步骤,我认为
template <typename U>
operator U()
{
// or C++03: U u(mX);
U u(std::forward<T>(mX));
return u;
}
Run Code Online (Sandbox Code Playgroud)