Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can关键字";明确的;是否在一个特定的模板实例化中从构造函数中删除?_C++_Templates_Explicit Conversion_Template Classes - Fatal编程技术网

C++ Can关键字";明确的;是否在一个特定的模板实例化中从构造函数中删除?

C++ Can关键字";明确的;是否在一个特定的模板实例化中从构造函数中删除?,c++,templates,explicit-conversion,template-classes,C++,Templates,Explicit Conversion,Template Classes,我正在尝试创建一个模板类来强制执行维度正确性(长度除以时间可以提高速度,等等) 短篇故事:“无量纲”是可能的实例之一。如果我可以允许所有实例化都显式地从double构造,并且允许“无量纲”实例化(并且只有无量纲实例化)隐式地从double构造,那将是很方便的 说来话长:我的模板类的布局如下 template<int iLength, int iTime, int iMass> class qty { double data; //Operators overloaded

我正在尝试创建一个模板类来强制执行维度正确性(长度除以时间可以提高速度,等等)

短篇故事:“无量纲”是可能的实例之一。如果我可以允许所有实例化都显式地从double构造,并且允许“无量纲”实例化(并且只有无量纲实例化)隐式地从double构造,那将是很方便的

说来话长:我的模板类的布局如下

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>

};
…但仅为
数量定义它。这是可行的。。。但我想我可以做得更好。如果我允许从double隐式转换为
qty
,那么添加double和
qty
就不需要特殊处理。用户的错误也会给出更多提示性的错误消息——尝试在速度上增加一个双精度表示转换是不可能的(理解维度不兼容的基本概念),而不是抱怨函数没有定义(这可能会导致用户怀疑模板类中有错误)

问题是我不能允许对任何其他模板参数组合进行隐式构造。如果我这样做了,那么任何数量的增加和加倍都会成功;我想强制用户考虑维度的正确性,并在添加之前将双常量显式转换为适当的维度(如果这是预期的操作)。然而,我确实希望允许从double显式构造——没有它,简单声明

qty<1,-1,0> a(1.5); //speed with value 1.5
<代码>数量a(1.5)//速度值为1.5
需要一个笨拙的转换函数

qty<1,-1,0> a = makeQty<1,-1,0>( 1.5 ); //my eyes hurt
qty a=makeQty(1.5)//我的眼睛疼
这意味着我真正想要的是

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 ???
模板
类别数量{
双重数据;
显式数量(constdouble&rhs):数据(rhs){}//常规版本
//隐式转换
//...
};
模板
qty::qty(constdouble&rhs):数据(rhs){}//显式实例化
//对于无量纲情形
// ... 通过黑魔法到reallow的隐式转换
//仅用于此实例化???

正如您所看到的,我不确定是否可以仅删除一个实例化的
显式
规范,如果可能的话,我不确定语法是什么。

您不能直接更改它,但以下内容将适用于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) {}
};
模板
类数量{
双重数据;
公众:
显式数量impl(constdouble&rhs):数据(rhs){}//常规版本
//隐式转换
//...
};
//一般情况:只需转发至_impl
模板
类别数量:公共数量{
//继承构造函数,包括“显式”
使用qty\u impl::qty\u impl;
};
//特例
模板
类别数量:公共数量{
使用qty\u impl::qty\u impl;
公众:
//提供非显式构造函数以重写继承的基构造函数
数量(常数双和rhs):数量(rhs){
};

这允许您为几乎所有内容保留一个通用实现,只需将非显式ctor转发到显式ctor。

我们创建了一个类型,它是
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>;
模板
结构块{
结构类型{type()=delete;运算符T();};//运算符T是标准的偏执狂
};
模板
结构块{
使用类型=T;
};
模板
使用block_除非t=typename block_除非::type;
模板
如果_t=块_,则使用块_,除非_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 );
};
模板
结构数量{
枚举{scalar=(a==0)&&&(b==0)&&&(c==0)};
解释数量(如果块小于标量,则块大于d);
数量(数据块,除非数据块<标量,双精度>d);
};
怎么样

在C++1y中,requires子句可能会做得更好


(标准的偏执是因为标准中的冗长,模板方法必须至少有一个有效的实例化:
操作符T
虽然不可访问,但意味着使用
d
的代码将在99%的上下文中工作,而在这些上下文中,代码需要一个

您不能更改成员声明,但是您可以为case
quaty
专门化整个模板。您看到了吗?实际上,您可以只定义两个相互排斥的SFINAE构造函数。@KerrekSB SFINAE在不依赖于该构造函数中的推断类型时将不起作用。@DanielFrey:Hm,至少您还必须将构造函数也制作成模板。但这真的没用,你说得对,我喜欢这个。我尝试了一下,但是现在我所有的操作符都返回类型qty\u impl,所以写qty=(操作返回qty\u impl)是一个编译错误。这可以避免吗?我尝试为接受qty impl的qty编写构造函数,但似乎无法解决问题…@user1476176您可以尝试CRTP变量,将
qty
作为模板参数传递到
qty impl
,并使用它来实现运算符。如果我理解正确,然后,
qty
有一个来自
block_的显式构造函数,除非::type
(由于该类型没有构造函数,因此无法调用该构造函数)和一个来自
double
的隐式构造函数,对于所有其他实例化,隐式/显式分类是反向的。酷!你能详述最后一段吗?如果没有
运算符T
,哪个模板方法不会有有效的实例化,而这不起作用的百分之一实例是什么?@user1476176标准中有一个模糊的段落规定
模板
函数必须至少有一个专用化,对于哪个专用化,insta
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 );
};