【发布时间】:2018-04-04 08:32:29
【问题描述】:
我尝试实现一个涉及模板的用户定义类型转换的小例子。
#include <cassert>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#include <type_traits>
template <typename T>
concept bool UIntegral = requires() {
std::is_integral_v<T> && !std::is_signed_v<T>;
};
class Number
{
public:
Number(uint32_t number): _number(number)
{
if (number == 1) {
number = 0;
}
for (; number > 1; number /= 10);
if (number == 0) {
throw std::logic_error("scale must be a factor of 10");
}
}
template <UIntegral T>
operator T() const
{
return static_cast<T>(this->_number);
}
private:
uint32_t _number;
};
void changeScale(uint32_t& magnitude, Number scale)
{
//magnitude *= scale.operator uint32_t();
magnitude *= scale;
}
int main()
{
uint32_t something = 5;
changeScale(something, 100);
std::cout << something << std::endl;
return 0;
}
我收到以下编译错误(来自 GCC 7.3.0):
main.cpp:在函数'void changeScale(uint32_t&, Number)'中:
main.cpp:40:15: error: no match for ‘operator*=’ (operand types are ‘uint32_t {aka unsigned int}’ and ‘Number’)
幅度 *= 比例;
注意注释掉的那一行——这行有效:
//magnitude *= scale.operator uint32_t();
为什么不能自动推导出模板化的转换算子?提前感谢您的帮助。
[编辑]
我遵循删除概念以使用 Clang 并查看其错误消息的建议。我得到了以下信息(这已被截断但足够了):
main.cpp:34:15: error: use of overloaded operator '*=' is ambiguous (with operand types 'uint32_t'
(aka 'unsigned int') and 'Number')
magnitude *= scale;
~~~~~~~~~ ^ ~~~~~
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, float)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, double)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, long double)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, __float128)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, int)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, long)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, long long)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, __int128)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, unsigned int)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, unsigned long)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, unsigned long long)
main.cpp:34:15: note: built-in candidate operator*=(unsigned int &, unsigned __int128)
因此,打开这些概念后,我假设将 Number 转换为 unsigned integer 类型的唯一方法 - 那么为什么编译器不足以推断转换?
【问题讨论】:
-
Clang 会给您一条错误消息,立即回答您的问题。
-
Clang 不支持概念,所以请澄清您的声明。
-
这个问题的概念是正交的,可以去掉概念声明,把UIntegral换成typename,结果是一样的。
-
您的概念定义要求
std::is_integral_v<T> && !std::is_signed_v<T>是一个有效的表达式;它对该表达式的 value 没有任何要求。你几乎肯定想要template<typename T> concept bool UIntegral = std::is_integral_v<T> && !std::is_signed_v<T>;。 -
完美,谢谢! :)
标签: c++ templates implicit-conversion c++-concepts c++20