这个C++模板宏的含义是什么?

6

请问有人能为我解释一下吗?我了解宏和模板,但是我不知道作者表达的意思。这个定义的使用目的是什么?为什么要这样写?我们在这里定义了什么?如何以及为什么使用这个东西?

#define MY_CLASS(RET_TYPE, ... )\
    template<typename Derived>\
    __VA_ARGS__\
    RET_TYPE my_class_impl<Derived>

我还有类似这样的东西

MY_CLASS( )::my_class_impl( int arg_id )

我也看到了。
template<typename Derived>
class my_class_impl

我从同事那里听说这是CRTP(奇特递归模板模式)的一个案例,但他没有更具体的见解。

此外,在后续中,我看到它被使用如下:

MY_CLASS(some_type)::find_desired_val(int x) {
// some code
}

所以,宏被用于在实际实现方法签名时替换类my_class_impl的签名?

2
my_class_impl 是什么? - Caninonos
typename Derived 看起来像是一个 CRTP 嵌套在宏中。对于 RET_TYPE...,有哪些合理的参数可以提供,以及为什么在没有任何参数的情况下调用该宏,我不知道。 - Quentin
@Quentin:我想到了__decltype(dllexport),但这是MSVC++的扩展。 - MSalters
这是一个 MSVC 特定的问题吗? - Timo
3
我认为这是一个合理的问题。提问者看到了代码,并希望理解它。鉴于它非常复杂,我不认为关闭它有任何理由。 - bolov
显示剩余3条评论
2个回答

10

它被用来定义my_class_impl<Derived>的成员函数。

MY_CLASS(void)::member(Bar b) {}

展开为:

template <typename Derived>
void my_class_impl<Derived>::member(Bar b) {}

变参宏参数可用于各种(标准或非标准)属性,例如__declspec(...)[[...]]等。例如:

MY_CLASS(void, __declspec(dllexport))::foo();

扩展为:

template <typename Derived>
__declspec(dllexport) void my_class_impl<Derived>::foo() {}

MY_CLASS()::my_class_impl(int arg_id)由于编译器扩展允许缺少宏参数(在MSVC、Clang和GCC上都有,我弄错了),会扩展为构造函数:

template <typename Derived>
/* nothing */ my_class_impl<Derived>::my_class_impl(int arg_id) {}

这也是一个相当丑陋的宏。不仅难以理解,而且隐藏了一些非常平凡的东西,并且如果你尝试返回一个包含逗号的类型(std::map<int,int>),它就会出错。


非常感谢,那很有道理。还有一个细节,如果 VA_ARGS 实际上代表一些额外的参数,方法签名将如何扩展?你能否提供具体的例子吗? - Baron Yugovich
@BaronYugovich 添加了示例。 - Quentin

2
RET_TYPE是函数的提示,特别是MY_CLASS这个提示是成员函数。这些函数也可以声明为static
不太常见的是[[noreturn]][[deprecated]],它们是C++14属性。 <Derived>部分与此无关,类模板和类一样可以有成员函数。

好的,是的,这是C++14。 - Baron Yugovich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接