【发布时间】:2017-11-02 17:11:30
【问题描述】:
假设我有一个仿函数,它使用标签调度从函数的多个实现中进行选择,如下所示:
// base class for all tags, indicating the "default" implementation
struct tag_base { };
// subclasses for tags that might select a different implementation
struct tag1 : tag_base { };
struct tag2 : tag1 { };
struct tag3 : tag2 { };
struct func
{
void operator()(tag_base) { }
void operator()(tag3) { }
};
因此,在这个简单的示例中,标签类型tag1 和tag2 将分派给func 的调用运算符,它采用默认实现tag_base。但是,tag3 会改为分派到不同的实现。我有兴趣在编译时检查,对于给定的函数类型func 和两个标签类型T 和U,它们是否会分派到func 的调用运算符的相同重载。
基本上,我想要这样的特征(只有伪代码,因为这种方法无法编译):
template <typename Func, typename T, typename U>
struct has_same_tag_overload
{
enum { value = (void (Func::*)(T)) &func::operator() ==
(void (Func::*)(U)) &func::operator() };
}
所以在上面的例子中,以下是正确的:
tag<func, tag_base, tag1>::value == 1tag<func, tag_base, tag2>::value == 1tag<func, tag1, tag2>::value == 1tag<func, tag1, tag3>::value == 0tag<func, tag2, tag3>::value == 0
这可能吗?增加难度,这在C++03中可以吗?
【问题讨论】:
-
@VTT 不,它没有,有两个原因:1. 你不能比较不同类型的指针是否相等,以及 2. 没有
void (func::*)(tag1)类型的重载,所以特征不适用于继承。 -
对不起,我把它转移到这里时打错了。 gcc 抱怨演员阵容无效;我想使用 T= tag1 和 U = tag2 来调用 trait,但是由于相应的重载取而代之的是 tag_base,所以它说强制转换是无效的。
-
@JasonR 这些函数实际上是
void,还是对 SO 的简化?如果您将返回类型更改为与标记参数相同,我希望您可以做到这一点,但即使在那时我也只会知道在 C++11 中使用decltype是如何做到的。 -
@VTT 我相信检查here 应该都可以工作,除了我用
static_assert编写它们的部分。检查重载是否存在只是其中的一部分,如果没有相关的重载,我们可能只能假设并拒绝编译。 -
@DanielH:函数不是
void,这是一种简化,但在某些情况下,两个不同标签的返回类型是相同的。
标签: c++ metaprogramming c++03