是否可以从一个特定模板实例化的构造函数中删除关键字"显式"?
Can keyword "explicit" be removed from a constructor in one specific template instantiation?
我试图创建一个模板类来强制尺寸正确性(长度除以时间得到速度,等等)。
短篇小说: "Dimensionless"是其中一个可能的实例。如果我可以允许所有实例化都可以从双精度显式构造,并且进一步允许"无维度"实例化(并且只有无维度实例化)可以从双精度显式构造,那将是很方便的。
长话短说:我的模板类布局为
template<int iLength, int iTime, int iMass>
class qty {
double data;
//Operators overloaded to enforce dimensional correctness
// e.g. qty<a,b,c> can only be added to qty<a,b,c>
// qty<a,b,c> * qty<a2,b2,c2> returns qty<a+a2,b+b2,c+c2>
};
按照这种样式,qty<0,0,0>
是一个无因次量,因此应该可以对qty<0,0,0>
和双精度进行加减。我目前通过声明
qty operator+ (const double& rhs) const;
…但只有为qty<0,0,0>
定义。这是可行的…但我觉得我可以做得更好。如果允许从双精度体到qty<0,0,0>
的隐式转换,那么添加双精度体和qty<0,0,0>
就不需要特殊处理。用户错误也会给出更多提示性的错误消息——试图向speed添加double将表明不可能进行转换(得到维度不兼容的基本概念),而不是抱怨函数没有定义(这会导致用户怀疑模板类中存在错误)。
问题是我不能允许任何其他模板参数组合的隐式构造。如果我这样做了,那么任何数量的加法和双精度总是成功的;我想迫使用户考虑维度的正确性,并在加法之前显式地将双精度常量转换为适当的维度(如果这是预期的操作)。然而,我确实希望允许从双精度对象中显式地构造——如果没有它,简单的声明
qty<1,-1,0> a(1.5); //speed with value 1.5
需要一个别扭的转换函数
qty<1,-1,0> a = makeQty<1,-1,0>( 1.5 ); //my eyes hurt
这意味着我真正想要的是
template<int iLength, int iTime, int iMass>
class qty {
double data;
explicit qty(const double& rhs) : data(rhs) {} //general version prohibits
//implicit conversion
//...
};
template<>
qty<0,0,0>::qty(const double&rhs) : data(rhs) {} //Explicit instantiation
//for dimensionless case
// ... with black magic to reallow implicit conversion
// for this instantiation only ???
正如您所看到的,我不确定是否有可能仅为一个实例删除explicit
规范,并且——如果可能的话——我不确定语法是什么。
我们创建的类型是T
或者是不能依赖bool类型创建的类型:
template<bool b, typename T>
struct block_unless {
struct type { type() = delete; operator T(); }; // operator T is standard-paranoia
};
template<typename T>
struct block_unless<true, T> {
using type = T;
};
template<bool b, typename T>
using block_unless_t = typename block_unless<b,T>::type;
template<bool b, typename T>
using block_if_t = block_unless_t<!b, T>;
然后我们保护我们想要阻止/激活的方法与其余代码内联:
template<int a, int b, int c>
struct qty {
enum { scalar = (a==0)&&(b==0)&&(c==0) };
explict qty( block_if_t< scalar, double > d );
qty( block_unless_t< scalar, double > d );
};
怎么样?
在c++ 1y中,require子句可能会做得更好。
(标准的偏执狂是因为标准中的术语,其中模板方法必须至少有一个有效的实例化:虽然不可访问,但operator T
意味着使用d
的代码将在99%的代码期望double
的上下文中工作。)
您不能直接更改它,但是下面的代码将在c++ 11中工作:
template<int iLength, int iTime, int iMass>
class qty_impl {
double data;
public:
explicit qty_impl(const double& rhs) : data(rhs) {} //general version prohibits
//implicit conversion
//...
};
// general case: simply forward to _impl
template<int iLength, int iTime, int iMass>
class qty : public qty_impl<iLength,iTime,iMass> {
// inherit ctors, including "explicit"
using qty_impl<iLength,iTime,iMass>::qty_impl;
};
// special case
template<>
class qty<0,0,0> : public qty_impl<0,0,0> {
using qty_impl<0,0,0>::qty_impl;
public:
// provide non-explicit ctor to override the inherited base ctors
qty(const double& rhs) : qty_impl<0,0,0>(rhs) {}
};
这允许你为几乎所有的东西保持一个共同的实现,并简单地将非显式的角色转发给显式的角色。
- 如何使用非默认构造函数实例化模板化类
- 有没有一种代码密度较低的方法来使用非默认构造函数初始化数组?
- 如何在 C++ 中使用它的构造函数初始化 unique_ptrs 的 2D 向量?
- 在C++中使用默认构造函数初始化对象的不同方法
- 使用默认构造函数初始化对象的不同方法
- 我们可以用参数化构造函数初始化结构的数组吗?
- 有没有办法使用该类的构造函数初始化另一个类的私有部分内的对象数组?
- C++ - 使用另一个类的构造函数实例化一个对象
- 类内初始化与构造函数初始化列表的顺序
- 在保证复制的世界中构造函数实例化
- 防止复制构造函数实例化 C++11 类"deleting"
- 为构造函数初始化引用实例变量提供默认值
- C 调用模板构造函数实例化
- C++.对象使用错误的构造函数实例化
- C++如何用参数化构造函数实例化对象
- 为什么无法使用复制构造函数实例化"non const"而可以在没有复制构造函数的情况下实例化配对?
- C++中函数返回的值是右值吗?无法使用复制/移动构造函数初始化实例
- 用自定义构造函数初始化c++类的实例作为Objective C类成员
- C++:当类被模板化时,如何在使用默认构造函数实例化后将输入放入对象中
- 如何使用已知的非默认构造函数实例化未知大小的可变参数元组