需要默认参数值的模板函数的首选设计是什么?

发布于 2024-08-07 04:24:23 字数 1167 浏览 3 评论 0原文

我目前正在清理一个充满函数模板的 API,并强烈希望编写以下代码。

template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

当我调用这个模板时,我想按如下方式执行。

std::string text("hello");
doWork(100, 20.0, &text);
doWork('a', text);         // oops!
doWork<char, std::string, void>('a', text);  // to verbose!

不幸的是,第二次调用无法编译,因为编译器无法推断可选参数的类型。这是不幸的,因为我真的不关心参数类型是什么,而是关心它的值为 NULL。另外,我想避免第三次调用的路线,因为它会妨碍可读性。

这导致我尝试使模板参数 V 具有默认类型,这也不起作用,因为您无法将默认类型应用于函数模板参数(至少使用 VC++ 9.0)。

template <typename T, typename U, typename V = void>  // oops!
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

我唯一剩下的选择是引入一个对模板参数 V 一无所知的 doWork 重载。

template <typename T, typename U>
void doWork(const T& arg1, const U& arg2)
{
    doWork(arg1, arg2, 0);
}

template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg);

这是解决这个问题的最佳方法吗?我看到的唯一缺点是,如果函数模板包含许多具有合适默认值的参数,我可能会引入许多琐碎的转发函数。

I'm currently working on cleaning up an API full of function templates, and had a strong desire to write the following code.

template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

When I invoke this template, I would like to do so as follows.

std::string text("hello");
doWork(100, 20.0, &text);
doWork('a', text);         // oops!
doWork<char, std::string, void>('a', text);  // to verbose!

Unfortunately, the second invocation doesn't compile since the compiler cannot deduce the type of the optional parameter. This is unfortunate, since I really don't care what the parameter type is, but rather that its value is NULL. Also, I'd like to avoid the route of the third invocation since it hampers readability.

This lead me to try to make the template argument V have a default type, which also doesn't work since you cannot apply a default type to a function template argument (at least using VC++ 9.0).

template <typename T, typename U, typename V = void>  // oops!
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

My only remaining option is to introduce an overload of doWork that knows nothing of the template argument V.

template <typename T, typename U>
void doWork(const T& arg1, const U& arg2)
{
    doWork(arg1, arg2, 0);
}

template <typename T, typename U, typename V>
void doWork(const T& arg1, const U& arg2, V* optionalArg);

Is this the best approach to solving this problem? The only drawback I see is that I could potentially introduce many trivial forwarding functions if a function template contains many parameters that have suitable defaults.

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

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

发布评论

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

评论(3

梦里的微风 2024-08-14 04:24:23

我认为您的转发功能是一个非常合适的解决方案,尽管在您的解决方案中,您不需要显式指定模板参数吗? (0 是一个整数常量,可以转换为任何 V* 类型。)还有 doWorddoWork

作为一般规则,尽量避免使用没有很强回报的可选参数。

强制函数的客户端在适当的情况下仅添加 , (void*)0 可能比添加更多额外机制来支持两个参数和一个参数更容易。模板的三个参数版本。但这取决于预期用途。

I think that your forwarding function is a perfectly suitable solution, although in your solution, won't you have to explicitly specify the template parameters? (0 is an integer constant that can be coverted to any V* type.) Also doWord vs doWork?

As a general rule, try to avoid optional parameters where they don't have a very strong pay-off.

It might be easier to force clients of you function to just add a , (void*)0 if appriopriate than add to much extra mechanism to support both a two parameter and a three parameter version of the template. It depends on the expected uses, though.

執念 2024-08-14 04:24:23

从客户端代码的角度来看,如果它没有第三个参数,为什么需要发明一个呢?

因此,如果您的目标是可用性和可读性,我同意您的包装方法:它非常有意义,并且编写的包装器负责第三个参数的合理值> 必要的。

最重要的是,如果需要的话,它可以为不同的专业化使用不同的默认值。

From the client code's point of view, if it doesn't have a third parameter, why does it need to invent one?

So if you aim for usability and readability, I agree with your wrapper method: it makes perfect sense, and the wrapper you wrote is responsible for a decent value of the third parameter you necessitated.

On top of that, it makes it possible to use a different default for different specializations, if needed.

乱世争霸 2024-08-14 04:24:23

一种可能性是重新排序模板参数,因此可选参数排在第一位。

template <typename V, typename T, typename U>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

doWork<void>('a', text); 

转发看起来也不错。

但默认参数和模板似乎不太匹配。

One possibility is to reorder the template arguments, so the optional one comes first.

template <typename V, typename T, typename U>
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0);

doWork<void>('a', text); 

Forwarding looks OK too.

But it seems default arguments and templates don't match well, though.

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