gpt4 book ai didi

c++ - 无法推断模板参数?

转载 作者:行者123 更新时间:2023-11-30 02:08:22 25 4
gpt4 key购买 nike

我有以下类(class)

template<typename hi_t, typename lo_t>
struct int_t
{
hi_t hi;
lo_t lo;

int_t() : lo(0), hi(0) {}
int_t(int value) : lo(value), hi( value<0u? -1: 0 ) {}
int_t(unsigned value) : lo(value), hi( 0 ) {}

int_t& operator+=(const int_t& rhs)
{
lo_t _lo = lo;

lo += rhs.lo;
hi += rhs.hi;
hi += (int)(lo < _lo);

return *this;
}

template<typename hi_t, typename lo_t>
inline friend int_t<hi_t, lo_t> operator+(const int_t<hi_t, lo_t>&, const int_t<hi_t, lo_t>&);
};

template<typename hi_t, typename lo_t>
int_t<hi_t, lo_t> operator+(const int_t<hi_t, lo_t>& lhs, const int_t<hi_t, lo_t>& rhs)
{ return int_t<hi_t, lo_t>(lhs) += rhs; }

当执行下面的代码时

typedef int_t<long long, unsigned long long> int128;

int main()
{
int128 i = 1024;
i = i + 20;
}

编译器产生错误:

'int_t<hi_t,lo_t> operator +(const int_t<hi_t,lo_t> &,const int_t<hi_t,lo_t> &)' : could not deduce template argument for 'const int_t<hi_t,lo_t> &' from 'int'

当我将模板运算符的代码放在类主体中时 - 从友元运算符中删除模板行 - 它可以工作,但是在类外部使用友元运算符它无法推断出运算符。我认为当编译器为这个模板运算符生成代码时,输​​入参数和返回值将是 int128 类型,因此从 int 转换为该类型应该没有问题。

更新

如果我们按照前面的示例在类中定义友元运算符

template<typename hi_t, typename lo_t>
struct int_t
{
hi_t hi;
lo_t lo;

int_t() : lo(0), hi(0) {}
int_t(int value) : lo(value), hi( value<0u? -1: 0 ) {}
int_t(unsigned value) : lo(value), hi( 0 ) {}

int_t& operator+=(const int_t& rhs)
{
lo_t _lo = lo;

lo += rhs.lo;
hi += rhs.hi;
hi += (int)(lo < _lo);

return *this;
}

friend int_t operator+(const int_t& lhs, const int_t& rhs)
{ return int_t(lhs) += rhs; }

};

试图在类外定义模板运算符时出现问题

最佳答案

这段代码比乍一看要复杂。最棘手的部分是友元函数的声明。你应该看看这个 answer关于与模板中的函数成为 friend 。简短的建议是删除模板化的 operator+ 并将其实现为类声明内部的非模板友元函数:

template<typename hi_t, typename lo_t>
struct int_t
{
// ...
friend int_t operator+(int_t lhs, const int_t& rhs ) {
return lhs+=rhs;
}
};

对于特定的错误,它可能没有那么大的帮助,甚至可能会造成混淆,但是您可以首先考虑一个模板,如果在类型推导之后它是一个完美匹配(即无需转换)。这意味着 int128_t + int 永远不会与左右手侧具有相同类型的模板化 operator+ 匹配,即使有转换。

上面提出的解决方案声明(并定义)了一个非模板函数。因为它是在类内部定义的,所以它只会被 Argument Dependent Lookup 考虑,因此只有当其中一个运算符是 int_t 时才会应用,如果它被 ADL 找到,那么它将是使用通常的非模板规则选择重载解析,这意味着编译器能够使用任何可能的转换到 lhs 或 rhs(其中之一必须是 int_t 实例化,如果它是由 ADL 找到,但它会转换另一个)。

关于c++ - 无法推断模板参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6982470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com