无参数可变参数模板上的不明确重载

发布于 2024-12-13 02:45:03 字数 2765 浏览 6 评论 0原文

相关:


考虑这对可变 参数模板:

template<typename Dummy>
bool All(Param& c) {
    return true;
}

template<typename Dummy, Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<Dummy, rest...>(c);
}

这可以工作并编译。但是,没有第一个模板参数怎么写呢?

听起来微不足道?嗯,我就是这么想的。 :-) 让我们考虑一些想法。

想法#1:

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}
template<>
bool All(Param& c) {
    return true;
}

行不通……当我尝试这样做时,我想到了专业化,但转念一想,这并不是它的工作原理。

在最初的示例中,我创建了两个不同的重载模板,第一个采用 1 个模板参数,第二个采用 2 个或更多模板参数。没有歧义,也不涉及专业化。 我说得对吗?

想法#2:

bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

显然行不通,All with rest...为空不会扩展为对非模板函数的调用。

想法#3:

让我们稍微重建一下解决方案。

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

这个是不行的,因为 All(c) 是不明确的。因此我需要有一个 0-arg 情况和一个 >0-arg 情况...或者 1-arg 情况和 >1-arg 情况呢?

想法#3.5:

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* f2, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<f2, rest...>(c);
}

是的,可以,但是包含copypasta(在本例中很简单,但可能更大!),因此我想说它并不比我开始的更好。只是另一种解决方法。

想法#4:

让我们尝试#1,但使用类而不是函数。

template<Func* f, Func* ...rest>
struct All {
    static bool func(Param& c) {
        return f(c) && All<rest...>(c);
    }
};
template<>
struct All {
    static bool func(Param& c) {
        return true;
    }
};

这看起来很有希望,因为我可以专门学习课程。但是,嘿,那是什么?

抱歉,未实现:无法将“rest ...”扩展为固定长度的参数列表

这不是 GCC 4.4 的东西吗?我使用的是 MinGW GCC 4.6.1 (tdm-1)。


不管怎样,我是否应该认为我不能以直接的方式做这样一个基本的事情?是否需要使用具有附加虚拟模板参数的解决方法来完成此任务?

或者是否有一个简单、正确的变体来指定零参数情况,这可以工作?

Related:


Consider this pair of variadic templates:

template<typename Dummy>
bool All(Param& c) {
    return true;
}

template<typename Dummy, Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<Dummy, rest...>(c);
}

This works and compiles. However, how to write it without the first template parameter?

Sounds trivial? Well, that's what I thought. :-) Let's consider some ideas.

Idea #1:

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}
template<>
bool All(Param& c) {
    return true;
}

Won't work... When I attempted this I had specialization in mind, but on the second thought that's not how it works.

In the original example I created two different templates of overloads, first taking 1 template parameter and second taking 2 or more. No ambiguities and no specialization involved. am I getting it right?

Idea #2:

bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

Won't work obviously, All<rest...> with rest... being empty won't expand to a call to a non-template function.

Idea #3:

Let's rebuild the solution a bit.

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

This one is a no-go, because All(c) would be ambiguous. Hence I need to have a 0-arg case and a >0-arg case... Or what about a 1-arg case and a >1-arg case?

Idea #3.5:

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* f2, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<f2, rest...>(c);
}

Yup, works, but contains copypasta (simple in this case but might be bigger!), hence I'd say it's no better than what I've started with. Just another workaround.

Idea #4:

Let's try #1 but with classes instead of functions.

template<Func* f, Func* ...rest>
struct All {
    static bool func(Param& c) {
        return f(c) && All<rest...>(c);
    }
};
template<>
struct All {
    static bool func(Param& c) {
        return true;
    }
};

This looks promising since I can specialize classes. But hey, what is it?

sorry, unimplemented: cannot expand 'rest ...' into a fixed-length argument list

Wasn't this a GCC 4.4 thing? I'm on MinGW GCC 4.6.1 (tdm-1).


Anyway, should I think that I cannot do such an elementary thing in a straightforward way? Is it required to use the workaround with an additional dummy template parameter to accomplish this task?

Or is there a simple, correct variant to specify the zero-argument case, which would work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迎风吟唱 2024-12-20 02:45:03

在这个问题的情况下,由于模板参数是非类型的,
如果我们准备一个带有默认模板参数的函数,例如
接下来,可以保存 Dummy 参数:

template<typename = void>
bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

但是,我不确定这是否始终适用。
对于更一般的情况,可能需要 std::enable_if 或类似的调度
(但这会使代码有点冗长)。

In this question's case, since template parameters are non-type,
if we prepare a function with default template argument like the
following, Dummy parameter can be saved:

template<typename = void>
bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

However, I'm not sure this is always applicable.
For more general case, std::enable_if or similar dispatch might be needed
(this will make the code a little lengthy though).

巴黎盛开的樱花 2024-12-20 02:45:03

看起来您的问题与此类似:
递归可变参数模板函数的编译错误

有两个答案应该工作;第一个是您的#3.5,第二个是您没有的。

Looks like your question is similar to this one:
Compilation Error on Recursive Variadic Template Function

There are two answers there that should work; one that is your #3.5 and the second is one you didnt have.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文