使用模板函数参数的隐式类型转换

4
如果我有一个期望接收某种类型的简单函数,例如:
class X
{
    public:
        X( int ){}
};

void fx( X  ) {}



fx( 1 ); // implicit converted to X(int); // fine!

如果我尝试对模板类型执行相同操作,那么它将无法正常工作。
template <typename T>
class Y
{
    public:
        Y( T ){};
};

template <typename T>
void fy( Y<T> );

fy( 2 ); // Y<int> expected, but it fails

有没有什么技巧可以强制转换?

需要隐式地进行操作,直接访问 fy 不是 所需的。我知道可以通过指定模板参数来强制所有模板;)


@Ron:抱歉我表述不够准确:对我来说,隐式获取很重要。在我的用例中,手动定义模板参数没有帮助。 - Klaus
Y<const int&>, Y<int>, Y<int&&> 都是可行的。你认为编译器会如何决定? - Jarod42
3个回答

4
隐式转换在模板参数推导中不会被考虑;模板参数T无法被推导出来。

类型推断不考虑隐式转换(除上面列出的类型调整之外):这是后续重载决议的工作。

您可以编写一个辅助函数模板。
template <typename T>
void helper(T&& t) {
    fy<std::decay_t<T>>(std::forward<T>(t)); // specify the template argument explicitly
}

那么

helper(2); // T will be deduced as int

好的,答案很简单:不行!:-) 因为我考虑编写一个需要隐式转换的帮助程序,编写一个显式的帮助程序与我的基本想法相反。 我的想法仅基于“隐式”转换,因此这根本不是一种可行的方法。谢谢! - Klaus
@songyuanyao:你可能想要使用std::decay_t<T>来处理(常量)引用。 - Jarod42

3

在参数中,你不能同时使用隐式转换和模板推导。另一种分解它的方法:

template <typename T>
void fy( T x ) {
    Y<T> y = x;
    //Use y
    return;
}

当然,根据fy的情况,您可以直接使用x作为T,并在函数中进行隐式转换。


如果您已经拥有fy(Y<T>)的代码,那么您只需编写template <class T> void fy(T x) { fy(Y<T>(x)); }作为重载包装即可。 - Tobias

1
模板参数推导不考虑任何隐式转换。
您可以手动指定所需的实例化:
fy<int>(2);

使用C++17中的模板类型推断,您还可以选择

fy(Y(2));

并且使用预C++17版本

fy(Y<int>(2));

很抱歉我表达得不够准确:对我来说,隐式获取它非常重要。在我的使用情况下,手动定义模板参数并没有帮助。 - Klaus

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