- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写代码并决定添加对标量类型的支持,以便能够在 std::complex<double>
之间切换和普通double
.我写了所有的数字运算,并用 template <typename Scalar>
模板化了它方法。
我的“问题”是,对于复杂的情况,我需要提供一些在实际情况下没有意义且无法编码的额外方法。
我以前的方法是创建一个基类模板,它实现了所有常见的东西。然后我有一个派生自这个基类的具体类,作为 Scalar
模板参数 std::complex<double>
.然后我有一种模板代理/虚拟类,它充当 double
之间的开关。版本和 std::complex<double>
.它看起来或多或少像下面这样。
//base stuff
template<typename Scalar>
class NumberCruncherBase{
Scalar stuff1();
Scalar stuff2();
Scalar stuff3();
}
//inherit base stuff and extend it
class NumberCruncherComplex : public NumberCruncherBase< std::complex<double> >{
std::complex<double> extra_stuff1();
}
//switch proxy
template<typename Scalar>
class NumberCruncher : public NumberCruncherBase<Scalar> {}
//specialization for complex to explicitly derive from the extension
//in case of complex
template<>
class NumberCruncher< std::complex<double> > : public NumberCruncherBase< std::complex<double> > {}
不管是否令人惊讶,这种方法的效果还不错。您可以从 NumberCruncher
中得出或直接来自具体的专门类型。也可以提供 NumberCRuncherReal
为了一致性,但这有点毫无意义。
但是,这种代码编写起来有点麻烦,而且重复的代码感觉很臃肿。我需要为基类中的每种构造函数提供包装器。
我最近发现了 boost
的 enable_if
这似乎可以满足我的需要。但我无法让它工作。我累了:
const Matrix op_My( typename enable_if<boost::is_complex<Scalar> >::type* dummy = 0 ) { return g*H_sum_S[2]; };
这是类声明中的一行,g++
说:
error: expected a constant of type ‘bool’, got ‘boost::is_complex<Scalar>’
我的问题是,这是实现我所追求目标的好方法吗?我应该怎么写。我试着关注 http://www.boost.org/doc/libs/1_54_0/libs/utility/enable_if.html .我使用 gcc 4.8.1。
最佳答案
你得到的具体错误是因为 enable_if 将 bool 作为第一个参数,但你传递给它一个类型。
boost::is_complex<Scalar> // <- this is a type
要获取 bool 值(真/假),您需要编写:
boost::is_complex<Scalar>::value // <- this is a bool value telling whether Scalar is complex
is_complex 结构继承自 true_type 或 false_type(取决于 Scalar 的类型),如果您想更详细地了解它的工作原理,请查阅它们;)
但是您的代码还有其他问题。 enable_if 需要依赖于调用函数时首先知道的模板参数,而不是类模板参数。你可以这样做:
template<typename Scalar>
class matrix
{
//...
public:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, typename std::enable_if<boost::is_complex<T>::value,int>::type = 0
>
void print() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, typename std::enable_if<!boost::is_complex<T>::value,int>::type = 0
>
void print() const;
//...
};
这将产生一个“开关”,根据类模板参数选择合适的类方法。我按照惯例选择将 enable_if 放在模板参数中而不是函数签名中。我发现这是一个更通用的解决方案,也更具可读性。
这是否是提供此功能的“最佳”方式,我不知道(我无法在脑海中想到任何主要缺点),但它可以解决问题。希望对您有所帮助:)
编辑 08/11/13:
我使用特定类型的 enable_if 结构,因为它允许我在两个函数之间进行 enable_if 切换,否则它们将具有完全相同的签名。使用 enable_if 的“常规”方法之一是将 enable_if 的结果用作模板参数的默认值,如下所示:
template<typename Scalar>
class matrix
{
//...
public:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, class = typename std::enable_if<boost::is_complex<T>::value>::type // enable_if is used to give default type for the class template
>
void print() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, class = typename std::enable_if<!boost::is_complex<T>::value>::type // same as above
>
void print() const; //<- this has same function signature as the above print()
// we get a compiler error
//...
};
编译器无法区分这两个打印函数,因为它们都以相同的方式模板化,并且具有相同的签名,因为它们都被视为
template<typename T, typename U>
void print() const;
在我的示例中,编译器不知道函数是如何模板化的,因为这是由 enable_if 的结果决定的
template<typename T, ?>
void print() const;
因此可以在函数被调用和 enable_if 被评估时首先看到函数签名。我按照惯例选择了 int,但你也可以使用 void*:
typename std::enable_if<!boost::is_complex<T>::value,void*>::type = nullptr
使用 void* 而不是 int,但不仅仅是 void,因为我们不能有 void 非类型模板参数。
要做你想做的事,你需要在你的派生类中提供一个非模板函数来覆盖基类中的抽象函数。为此,您可以使用 indirection 并执行以下操作:
class matrix_base
{
public:
virtual void print() const = 0;
};
template<typename Scalar>
class matrix: matrix_base
{
//...
private:
// print function that will be called for a matrix of complex numbers
template<typename T=Scalar
, typename std::enable_if<boost::is_complex<T>::value,int>::type = 0
>
void print_impl() const;
// print function that will be called for a matrix of non-complex numbers
template<typename T=Scalar
, typename std::enable_if<!boost::is_complex<T>::value,int>::type = 0
>
void print_impl() const;
public:
// print function that will override abstract print in base class
void print() const { print_impl(); } // <- redirect to one of the print_impl() functions
//...
};
这种方法的缺点是您需要为每种可能的矩阵类型提供一个 print_impl() 实现,即您不能只为复数提供一个 print_impl(),您还需要为非复数提供一个。
希望这能让一些事情更清楚 :)
关于c++ - 根据模板类型在类中提供/启用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19840918/
我想知道如何首先检测 Javascript 是否启用/禁用。在此站点上禁用 javascript 表明 stackoverflow 使用了称为标签的东西。 这是标准的做法吗?它适用于所有浏览器吗?它不
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: How to enable PHP short tags ? Enable short open tags
在 VSTS (Azure DevOps) 上拥有私有(private)存储库我尝试通过将以下内容添加到 .csproj 文件来启用 SourceLink:https://github.com/dot
我创建了一个 wx.Frame(我们称之为 mainFrame)。该框架上包含一个按钮,当单击该按钮时,会创建一个新框架(我们称之为 childFrame)。 我想知道如何在创建 childFrame
当我禁用 WPF 中的控件时,比如说一个菜单项 MenuItem aMenuItem = ... aMenuItem.IsEnabled = false; MenuItem 中的文本仍然处于事件状态,
我想在我的 nginx 服务器上启用 gzip 压缩。 nginx.conf 文件在这里: http { # Enable Gzip server { location ~* \.(?
我正在使用免费的 heroku 附加 PG 备份并遵循这些 instructions .我找到了安装应用程序的命令:heroku addons:add pgbackups:auto-week。但是我想
我想知道脚本是否可以使用某种切换按钮启用/禁用页面上的所有输入元素。 我用谷歌搜索了它,但除了这个之外没有发现任何有用的东西: http://www.codetoad.com/javascript/e
在我的 php 文件中,我想使用 jQuery Datepicker。 当我的文件加载时,我创建了禁用的日期选择器。 然后,当我的 php 文件(它是一个表单)中的一个特殊字段被填充时,我想启用日期选
我有一个按钮,如下所示: RadButton lnkAdd = new RadButton(); lnkAdd.ID = "BtnAdd"; lnkAdd.CommandName = RadGrid.
public static void ToggleTaskManager(string keyValue) { RegistryKey objRegistryK
我正在 Azure 中使用事件网格订阅,该订阅在创建 Blob 时触发。然而,我们有很多文件进入这个 blob,比如说 1000 多个。 如果我发现任何文件有任何错误,我想做的是禁用事件订阅。 最佳答
我的网站上有几个使用 HTML5 contentEditable 属性的 div。目标是让用户能够开始编写日记条目,并将保存按钮从禁用更改为启用。 这是我目前拥有的 HTML: Write
我有一个范围输入,其定义如下: @Html.LabelFor(m => Model.Quality, Resources.CompressionQuality) 和一个下拉菜单: @Html.Lab
我正在尝试创建一个启用/禁用按钮的下拉菜单,并且我正在关注此 example 但它已经有 4 年历史了,而且该功能似乎无法在我的 xhtml 页面上运行。 任何帮助都将被适当 最佳答案 这是一个现场演
我正在 Azure 中使用事件网格订阅,该订阅在创建 Blob 时触发。然而,我们有很多文件进入这个 blob,比如说 1000 多个。 如果我发现任何文件有任何错误,我想做的是禁用事件订阅。 最佳答
我在这里遇到一个非常奇怪的情况:我编写了一个应用程序,除其他外,将连接的代理从打开切换到关闭,反之亦然。通过更改注册表中的值来完成此操作: public void SetUpProxy(string
我需要调整一堆 PVC 的大小。似乎最简单的方法是通过ExpandPersistentVolumes 功能。但是我无法获得配置合作。 ExpandPersistentVolumes feature g
如果我的TextField为空,则应禁用该按钮,并且该按钮的textColor和borderColor应该为灰色。但是,启用按钮后,颜色应为蓝色。 更改textColor很容易: button.Set
您好,我的问题是:我无法从另一个类启用表单的按钮。我的表单类是 public class FileSending { //Function for enabling the button
我是一名优秀的程序员,十分优秀!