如何避免隐式转换类型
How to avoid implicitly convertible types
更新
如果有人对诉讼感兴趣,则GitHub项目就在这里。尽管它运行良好,但我只将其调整为算术类型。
未来的发展将带来更多。
谢谢大家
原始帖子
是的,我知道这个问题。请阅读,以进行良好的介绍。还有一个聪明但不是普遍的解决方案。
我确实在乎这一点,但是我也需要像非可转换一样,一些基本类型。拥有这种情况将严重限制引入错误的可能性。不仅允许使用隐式转换,而且还用于可变创建,作业,比较等。
我确定这已经尝试过甚至可能已经解决。我在程序中不能有这个:
// implicit conversions
// no warnings
{
char character = 127 ;
bool truth = 0 ;
size_t size_ = truth ;
int integer = false ;
size_ = integer;
size_ = character ;
}
在我的VS 2017(最新)中,该编译在默认设置中即使在Level 4
又称/W4
上也没有警告。Clang 7等也是如此
到目前为止,我已经设法开发了这个:
namespace dbj {
namespace util {
using namespace std;
template<typename T>
struct nothing_but final
{
static_assert(false == std::is_array_v<T>,
"can not deal with arrays");
using type = nothing_but;
// default creation
nothing_but() : val_(T{}) {}
// allowed conversion
nothing_but(T const & t_) : val_(t_) {}
// allowed assignment
type & operator = (T const & new_val_)
{
val_ = new_val_;
return *this;
}
/*
explictly ban all attempts to construct from
any other type but T
*/
template<
typename X,
std::enable_if_t<
false == std::is_same_v<T, X>
, int> = 0
>
nothing_but(X const & x_) = delete;
/*
explictly ban all attempts to assign from
any other type but T
*/
template<
typename X,
std::enable_if_t<
false == std::is_same_v<T, X>
, int> = 0
>
type & operator = (X const & new_val_) = delete;
/* conversion to X is banned */
template<
typename X,
std::enable_if_t<
false == std::is_same_v<T, X>
, int> = 0
>
operator X & () = delete;
// conversion to T is allowed, but const stays const
operator T & () { return val_; }
// non const value, as other std class types do
T & data() const { return (T&)val_; }
private:
T val_{};
// compatibility
friend bool operator < ( type const & left_, type const & right_)
{
return left_.val_ < right_.val_;
}
};
} // util
} // dbj
一些快速测试:
{
using dbj::util::nothing_but;
nothing_but<int> si1 = 42;
si1 = 42;
nothing_but<int> si2 = 13;
//nothing_but<int> si3 = true ;
//si3 = true;
//nothing_but<int> si4 = '$' ;
//si4 = '$';
//nothing_but<int> si5 = 2.7 ;
//si5 = 2.7;
//nothing_but<int> si6 = size_t(BUFSIZ) ;
//si6 = size_t(BUFSIZ);
si1 = si2; (void)(si1 == si2);
int j = 9;
nothing_but<int *> sip1 = &j;
nothing_but<char const *> scc1 = "OK";
char name[] = "c++";
// scc1 = name;
}
和一些constness测试
{ // constnes
const int cc = 42;
const int cb = cc;
nothing_but<int> const & sci1 = cc;
nothing_but<int> const sci2 = sci1 ; // ok
const nothing_but<int> sci3 = sci1 ; // ok
wprintf(L"%d", sci1.data()); // ok
//sci2 = sci1;
//const int ii1 = sci1;
//const int ii2 = static_cast<int>(sci1);
//const int * ii3 = const_cast<int *>(&(sci1));
const int & ii3 = (const int &)(sci1); // ok
int & ii4 = (int &)(sci1); // ok
}
{ // compatibility
// std::vector<nothing_but<bool>> bv{ true, 1 , true };
std::vector<nothing_but<bool>> bv{ true, true , true };
nothing_but<bool> bb = bv[1] ;
bool kb = bb; // OK
//int k = bb;
//int j = bv[1];
std::map< nothing_but<bool>, nothing_but<int> > bm;
bm[true] = 1;
// bm[true] = 2.3;
bm[false] = 0;
// bm[false] = 0.9;
}
等等。所评论的任何内容都不会编译。
到目前为止,我可以看到潜力,但我不确定我是否做对吗?您会认为这是有用的吗?如果您这样做会有所不同吗?
请注意,我需要通用解决方案,我称为"非可转换基本类型"。我希望可以做到,并且完成后可能很小且通用。
您可以使用"方法模板过载"而不是Type_traits进行操作:
template<typename T>
struct nothing_but final
{
// construction
nothing_but() = default;
nothing_but(const T& t_)
: val_(t_)
{}
template<typename Other>
nothing_but(const Other&) = delete;
// assignment
nothing_but& operator=(const T& new_val_)
{
val_ = new_val_;
return *this;
}
template<typename Other>
nothing_but& operator=(const Other&) = delete;
// comparison
bool operator==(const nothing_but& rhs) const
{
return (val_ == rhs.val_);
}
bool operator<(const nothing_but& rhs) const
{
return (val_ < rhs.val_);
}
// conversion
operator T& ()
{
return val_;
}
template<typename Other>
operator T& () = delete;
// non const value, as other std class types do
T& data() const
{
return (T&)val_;
}
template<typename Other>
operator Other& () = delete;
private:
T val_{};
};
非模板比模板优选(请参见C 标准13.3.3,或在http://www.gotw.ca/gotw/049.htm中进行了解释。
相关文章:
- 无法转换类型 C++
- 包含可变参数包的第一个可转换类型的别名的结构
- 将 std::conditional 与不可转换类型(原始与指针)一起使用
- 链接方法时出现转换类型错误
- 如何避免隐式转换类型
- 在多重继承场景中动态强制转换类型
- 编译器不支持的转换类型
- 错误调用功能无法转换类型
- 我想看到一个在整个后缀表达式的上下文中查找转换类型 id 的示例
- 对于动态类型为强制转换类型的对象,dynamic_cast失败
- 无法在初始化中转换类型
- 如何让"auto"转换类型
- 如何通过强制转换类型指针将字符数组转换为uint16_t
- 如何从新运算符+(Template类)返回具有转换类型的对象
- 带有模板的基于枚举的工厂无法转换类型
- 使用SWIG类型映射通过字符串转换类型
- 对于可转换类型,设计比循环依赖项更好
- SWIG不能正确转换类型定义
- 将类型转换扩展到可转换类型的对/元组
- 想要将字符数组的部分转换/类型转换为值