1

我目前正在清理一个充满函数模板的 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);

我唯一剩下的选择是引入一个doWork对模板参数一无所知的重载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);

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

4

3 回答 3

5

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

作为一般规则,请尽量避免可选参数,因为它们没有很强的回报。

强制你的客户只添加一个if appripriate可能, (void*)0比添加更多额外的机制来支持模板的两个参数和三个参数版本更容易。不过,这取决于预期的用途。

于 2009-10-11T19:37:54.263 回答
2

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

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

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

于 2009-10-11T20:03:46.177 回答
0

一种可能性是重新排序模板参数,因此可选的参数首先出现。

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

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

转发看起来也不错。

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

于 2009-10-11T19:56:52.340 回答