如何判断一个类是否有特定的模板化成员函数?

2024-01-23

我想知道是否可以扩展 SFINAE 方法来检测类是否具有某个成员函数(如此处讨论的:

“C++ 中有没有一种技术可以知道一个类是否具有给定签名的成员函数?”检查类是否具有给定签名的成员函数 https://stackoverflow.com/questions/87372/is-there-a-technique-in-c-to-know-if-a-class-has-a-member-function-of-a-given-s

) 支持模板化成员函数?例如。能够检测以下类中的函数 foo:

struct some_class {
   template < int _n > void foo() { }
};

我认为可以对 foo 的特定实例执行此操作(例如检查是否void foo< 5 >()是会员)如下:

template < typename _class, int _n >
class foo_int_checker {

  template < typename _t, void (_t::*)() >
  struct sfinae { };

  template < typename _t >
  static big
  test( sfinae< _t, &_t::foo< _n > > * );

  template < typename _t >
  static small
  test( ... );

public:

  enum { value = sizeof( test< _class >( 0 ) ) == sizeof( big ) };

};

Then do foo_int_checker< some_class, 5 >::value检查是否some_class有会员void foo< 5 >()。然而在 MSVC++ 2008 上总是会返回false而 g++ 在该行给出以下语法错误test( sfinae< _t, &_t::foo< _n > > );

test.cpp:24: error: missing `>' to terminate the template argument list
test.cpp:24: error: template argument 2 is invalid
test.cpp:24: error: expected unqualified-id before '<' token
test.cpp:24: error: expected `,' or `...' before '<' token
test.cpp:24: error: ISO C++ forbids declaration of `parameter' with no type

两者似乎都失败了,因为我试图从本身就是模板参数的类型获取模板函数实例化的地址。有谁知道这是否可能,或者是否由于某种原因被标准禁止?

编辑:看来我错过了::template让 g++ 正确编译上述代码的语法。如果我将获取函数地址的位更改为&_t::template foo< _n >然后程序编译,但我得到与 MSVC++ 相同的行为(value始终设置为false).

如果我注释掉...超载的test为了强制编译器选择另一个,我在 g++ 中收到以下编译器错误:

test.cpp: In instantiation of `foo_int_checker<A, 5>':
test.cpp:40:   instantiated from here
test.cpp:32: error: invalid use of undefined type `class foo_int_checker<A, 5>'
test.cpp:17: error: declaration of `class foo_int_checker<A, 5>'
test.cpp:32: error: enumerator value for `value' not integer constant

其中第 32 行是enum { value = sizeof( test< _class >( 0 ) ) == sizeof( big ) };线。不幸的是,这似乎并不能帮助我诊断问题:(。MSVC++ 给出了类似的不伦不类的错误:

error C2770: invalid explicit template argument(s) for 'clarity::meta::big checker<_checked_type>::test(checker<_checked_type>::sfinae<_t,&_t::template foo<5>> *)'

在同一条线上。

奇怪的是,如果我从特定类获取地址而不是模板参数(即而不是&_t::template foo< _n > I do &some_class::template foo< _n >)然后我得到正确的结果,但是我的检查器类仅限于检查单个类(some_class) 为函数。另外,如果我执行以下操作:

template < typename _t, void (_t::*_f)() >
void
f0() { }

template < typename _t >
void
f1() {
  f0< _t, &_t::template foo< 5 > >();
}

并打电话f1< some_class >()然后我没有得到编译错误&_t::template foo< 5 >。这表明,仅当在 SFINAE 上下文中从本身就是模板参数的类型获取模板化成员函数的地址时,才会出现问题。啊!


Boost.MPL 中已经实现了类似的功能,称为“BOOST_MPL_HAS_XXX_TRAIT_DEF”。看:

http://www.boost.org/doc/libs/1_41_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html http://www.boost.org/doc/libs/1_41_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html

它可以检测该类是否具有给定的命名type.

另外,对于您的具体情况,不要将函数指针作为参数传递(void (_t::*)()),而是尝试在方法的主体中使用它,即类似:

template < typename _t >
static big test( sfinae<_t> )
{
  &_t::foo<_n>;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何判断一个类是否有特定的模板化成员函数? 的相关文章

  • 格式说明符%02x

    我有一个简单的程序 include
  • 是否需要销毁运算符删除的形式才能真正销毁对象?

    C 20 添加了破坏形式operator delete区别于std destroying delete t范围 它导致delete表达式在调用之前不再销毁对象operator delete 目的是在显式调用对象的析构函数和释放内存之前 允许
  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • 关于逻辑/算法的想法以及如何防止线程写入 Sql Server 中的竞争

    我有以下逻辑 public void InQueueTable DataTable Table int incomingRows Table Rows Count if incomingRows gt RowsThreshold async
  • 无法继承形状

    为什么我不能使用继承 a 的类Shapes class http msdn microsoft com en us library ms604615 28v vs 90 29 我需要延长Rectangle具有一些方法的类 但我想以与使用相同
  • Boost ASIO 串行写入十六进制值

    我正在使用 ubuntu 通过串行端口与设备进行通信 所有消息都必须是十六进制值 我已经在 Windows 环境中使用白蚁测试了通信设置 并得到了我期望的响应 但在使用 Boost asio 时我无法得到任何响应 以下是我设置串口的方法 b
  • 在 Mono 中反序列化 JSON 数据

    使用 Monodroid 时 是否有一种简单的方法可以将简单的 JSON 字符串反序列化为 NET 对象 System Json 只提供序列化 不提供反序列化 我尝试过的各种第三方库都会导致 Mono Monodroid 出现问题 谢谢 f
  • 2个对象,完全相同(除了命名空间)c#

    我正在使用第三方的一组网络服务 但遇到了一个小障碍 在我手动创建将每个属性从源复制到目标的方法之前 我想我应该在这里寻求更好的解决方案 我有 2 个对象 一个是 Customer CustomerParty 类型 另一个是 Appointm
  • 如何修复错误:“检测到无法访问的代码”

    我有以下代码 private string GetAnswer private int CountLeapYears DateTime startDate return count String answer GetAnswer Respo
  • Libev,如何将参数传递给相关回调

    我陷入了 libev 中争论的境地 通常 libev 在类似的函数中接收包 接收回调 没关系 但是实际操作中 我们需要派遣一个亲戚 写回调 根据收到的包裹处理具体工作 例如 S RECV MSG pstRecvMsg S RECV MSG
  • 来自嵌入图像的 BitmapSource

    我的目标是在 WPF 窗口上重写 OnRender 方法中绘制图像 someImage png 它是嵌入资源 protected override void OnRender System Windows Media DrawingCont
  • LinkLabel 无下划线 - Compact Framework

    我正在使用 Microsoft Compact Framework 开发 Windows CE 应用程序 我必须使用 LinkLabel 它必须是白色且没有下划线 因此 在设计器中 我将字体颜色修改为白色 并在字体对话框中取消选中 下划线
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • 如何从 Boost.PropertyTree 复制子树

    我有一些boost property tree ptree 我需要树来删除一些具有特定标签名称的元素 例如 xml 表示源ptree如下
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来
  • 以编程方式创建 Blob 存储容器

    我有一个要求 即在创建公司时 在我的 storageaccount 中创建关联的 blob 存储容器 并将容器名称设置为传入的字符串变量 我已尝试以下操作 public void AddCompanyStorage string subDo
  • 如何在C#中控制datagridview光标移动

    我希望 datagridview 光标向右移动到下一列 而不是在向单元格输入数据后移动到下一行 我试图通过 dataGridView1 KeyDown 事件捕获键来控制光标 但这并不能阻止光标在将数据输入到单元格后移动到下一行 提前感谢你的
  • 如何高效计算连续数的数字积?

    我正在尝试计算数字序列中每个数字的数字乘积 例如 21 22 23 98 99 将会 2 4 6 72 81 为了降低复杂性 我只会考虑 连续的数字 http simple wikipedia org wiki Consecutive in
  • 声明一个负长度的数组

    当创建负长度数组时 C 中会发生什么 例如 int n 35 int testArray n for int i 0 i lt 10 i testArray i i 1 这段代码将编译 并且启用 Wall 时不会出现警告 并且似乎您可以分配
  • 如何在 ASP.NET Core 中注入泛型的依赖关系

    我有以下存储库类 public class TestRepository Repository

随机推荐