4

我一直在尝试摆脱一些旧代码中的警告(必须使用 MSVC 2005,目前正在使用 32 位构建),但一直在努力摆脱size_tto unsigned intconversion 警告。我们有自己Array<T> 的增长数组的实现,它实现了一个

template<typename I> const T& at(const I i) const {return atImpl(i);}

方法。当被称为

size_t i = 10; myArray.at(i);

我收到conversion from 'size_t' to 'const unsigned int', possible loss of data警告。一种工作理论被理解Iunsigned int,这导致编译器在传递到时将size_t其转换/转换为(这将是不方便但可以接受的)。但是,我无法在最小工作示例(本文底部)和更复杂的最小示例中重现此警告。简单地转换参数以使警告消失并且足以满足我们的需要(根据合同,数字适合)unsigned intiatunsigned intunsigned int

  1. 我对Iunsigned int这样的调用中的理解是否正确(规范说“ A typedef-name 因此是另一种类型的同义词。A typedef-name 不会引入新类型”,typeid(size_t(1)).name()unsigned int 并且size_t似乎被typedef喂了)。换句话说,最小的例子应该还是不应该给出警告?据我所知,构建配置是相同的。
  2. 由于我们的代码给了我们警告而最小的例子没有,所以我必须忽略一些东西。尽管付出了很多努力,但我无法弄清楚是什么。想法?

谢谢

最小的例子:

    template<typename T>
    class A
    {
      int t;
    public:
      template<typename I> T& at(const I i) { return t;}  
    };

    int main()
    {  
      size_t i = 10;
      A<int> a; 
      a.at(i) = 5; // no warning, why?
      return 0;
    }
4

1 回答 1

2

at 函数也是模板化的。C++ 将尝试推断模板类型参数。这是您的代码中发生的情况,因为您没有在调用中指定类型,例如 a.at< size_t>(1);

此代码将生成警告,因为它已将类型推断为 unsigned int,然后我们尝试传递 size_t

template <typename T>
class A
{
    int t;
    public:
        template<typename I> T& at(const I i)
        { return t;}
};

int main()
{
    unsigned int j = 5;
    size_t i = 10;
    A<int> a;

    a.at(j) = 4; // deduce template type as unsigned int
    a.at(i) = 5; // generate warning
    return 0;
}

编辑:我实际上在 VS 中尝试了这段代码,它会生成警告。

Edit2:在我尝试过的代码中 size_t 和 unsigned int 也是 4 个字节。所以我做了一些挖掘。在旧版本的 VS 中 size_t 被定义为typedef __w64 unsigned int size_t '__w64' 现在已被弃用,但用于标记在移动到 64 位平台时具有不同大小(例如 64 与 32)的类型。__w64 导致编译器将其size_t视为不同的类型。

作为一个实验,我键入了我自己的 unsigned intmyint并将行更改size_t i = 10myint i = 10.

usingtypedef __w64 unsigned int myint会生成警告,而 'typedef unsigned int myint` 不会生成警告。

于 2012-03-20T12:40:38.743 回答