模板的隐式类型转换 [英] Implicit type conversion with template

查看:213
本文介绍了模板的隐式类型转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有模板类A

template <unsigned int m>
class A
{
public:
    A(int) {}
};

其中具有 int 中的构造函数。我有一个操作:

Which has a constructor from int. And I have an operation:

template<unsigned int m>
A<m> operator+(const A<m>&, const A<m>&)
{
    return A<m>(0);
}

但是当我打电话时:

A<3> a(4);
A<3> b = a + 5;
A<3> c = 5 + a;

我希望 int 被隐式转换到A,但是编译器会抛出错误。

I would like int to be implicitly converted to A, but compilers throws error.

有没有任何优雅的方法来启用隐式转换,而无需使用以下解决方案:

Is there any elegant way to enable implicit conversion without using such solutions as:


  • a + A(5)

  • 运算符+< 3>(a,5)

  • a + A<m>(5)
  • operator+<3>(a, 5)

推荐答案

解决方案已显示在此答案中。现在,更多有关该问题的信息……

The solution is already shown in this answer. Now, more about the problem...

您的代码中的问题是如何执行重载解析。当考虑将模板函数用于重载解析时,编译器将对参数执行类型推导,并提出与调用匹配的类型替换,否则编译器将无法应用该模板,将其从潜在候选对象集中删除并继续。此时的问题是类型推导仅推导完全匹配(可能带有额外的const / volatile限定)。因为匹配是精确的,所以编译器将不使用任何转换(同样,除了cv之外)。

The problem in your code is how overload resolution is performed. When a template function is considered for overload resolution the compiler will perform type deduction on the arguments and come up with a type substitution that matches the call or else it fails to apply that template, removes it from the set of potential candidates and continues over. The problem at this point is that type deduction only deduces exact matches (with possible extra const/volatile qualification). Because the matching is exact, the compiler will not use any conversion (again, other than cv).

最简单的例子是 std :: max std :: min 函数:

The simplest example of this happens with std::max and std::min functions:

unsigned int i = 0;
std::min( i, 10 );    // Error! 

类型推导将推导 template< typename T>中的T。 min(T const& ;, T const&)对于第一个参数为 unsigned ,但 int 二者有所不同,编译器将放弃此模板函数。

Type deduction will deduce the T in template <typename T> min( T const &, T const & ) to be unsigned for the first argument but int for the second they differ and the compiler will discard this template function.

answer 使用的语言功能使您可以在类定义中定义非成员好友功能。模板的优点在于,对于模板的每个(不同)实例化,编译器都会在命名空间级别创建一个免费的非模板函数,该函数具有通过将其实例化的实际类型替换为好友声明而获得的签名:

The solution proposed in the answer is using a feature of the language that enables you to define a non-member friend function inside the class definition. The advantage with templates is that for every (different) instantiation of the template, the compiler will create a free non-template function at namespace level that has the signature obtained by substituting the real types of the instantiation in the friend declaration:

template <typename T>
class test {
    friend test operator+( test const & lhs, test const & rhs ) {  // [1]
        return test();
    }
}
test<int> t;                                                       // [2]

在上面的示例中,编译器允许您添加朋友的定义函数在[1]的类范围内。然后,当您在[2]中实例化模板时,编译器将生成一个自由函数:

In the example above, the compiler allows you to add the definition of the friend function inside the class scope at [1]. Then when you instantiate the template in [2], the compiler will generate a free function:

test<int> operator+( test<int> const & lhs, test<int> const & rhs ) { 
   return test<int>();
}

该函数始终定义为 是否(与按需实例化的模板类成员函数不同)。

The function is defined always, whether you use it or not (this differs to the template class member functions, that are instantiated on demand).

这里的魔术有很多方面。第一部分是一般,您正在为每种实例化类型定义所有非模板函数,因此您将获得通用性,同时获得重载解析能够使用此函数的优势当参数不完全匹配时。

The magic here has multiple sides to it. The first part is that it generically you are defining non-template functions for each and all of the instantiated types, so you gain genericity and at the same time the advantage of overload resolution being able to use this function when the arguments are not perfect matches.

由于它是非模板函数,因此编译器可以在两个参数上调用隐式转换,您将获得预期的结果行为。

Because it is a non-template function, the compiler is able to call implicit conversions on both arguments, and you will get your expected behavior.

另外,魔术的类型也不同,因为这样定义的功能只能通过依赖于参数的查找来找到除非也要在命名空间级别上声明,但在我们的情况下,这不能以通用方式完成。这可能是好是坏,取决于您要如何考虑...

Additionally, a different type of magic goes on with lookup, as the function so defined can only be found by argument dependent lookup unless it is also declared at namespace level, which in our case cannot be done in a generic way. The implication of this might be good or bad, depending on how you want to consider it...

由于只能由ADL找到,因此除非考虑至少有一个参数已经具有所需的类型(即,将永远不会将其用于执行对两个参数的转换)。缺点是,除非您实际上正在调用 ,否则不可能引用该函数,这意味着您无法获得函数指针。

Because it can only be found by ADL it will not be considered unless at least one of the arguments is already of the desired type (i.e. it will never be used performing conversions to both arguments). The downside is that it is impossible to refer to the function unless you are actually calling it, and that means that you cannot obtain a function pointer.

(有关模板友谊的更多信息,请参见此处,但请注意,在这种特殊情况下,所有其他变体将无法执行隐式操作转换)。

(More on template friendship here, but note that in this particular case, all the other variants will fail to perform implicit conversions).

这篇关于模板的隐式类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆