PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, April 28, 2022

[FIXED] How to detect implicit conversion losses integer precision on std::vector::emplace_back

 April 28, 2022     c++, emplace, implicit-conversion, vector, warnings     No comments   

Issue

I compiled the following code with -Wconversion compiler option to detect implicit conversion loses integer precision:

#include <vector>
#include <cstdint>

int main() {
    std::vector<std::uint16_t> v;
    std::uint32_t a = 0;
    v.emplace_back(a);  // no warning
    v.push_back(a);     // warning: implicit conversion loses integer precision
}

Compiling Demo https://wandbox.org/permlink/K5E4sUlfGBw6C5w8

The vector's value_type is std::uint16_t. If I push_back std::uint32_t value to the vector, then I got the following warning as I expected.

prog.cc:8:17: warning: implicit conversion loses integer precision: 'std::uint32_t' (aka 'unsigned int') to 'std::__1::vector<unsigned short, std::__1::allocator<unsigned short> >::value_type' (aka 'unsigned short') [-Wimplicit-int-conversion]
v.push_back(a);     // warning: implicit conversion loses integer precision
  ~~~~~~~~~ ^
1 warning generated.

However, if I emplace_back the same value to the vector, no warning is detected.

I've tested it clang++ 10.0.0, clang++ 9.0.0, and g++ 9.3.0 and got the same result.

Is there any good way to detect implicit conversion losses integer precision on std::vector::emplace_back ?


Solution

There is no implicit conversion when you call v.emplace_back(a). There would be an implicit conversion if you called v.emplace_back<const std::uint16_t &>(a).

A key difference between push_back and emplace_back is that the latter is a template while the former is not. If you do not specify a template argument for emplace_back, the compiler deduces it from the function argument, which means no conversion will be necessary at the point of call. Within emplace_back the conversion happens in a system header, which suppresses the warning.

So in your example,

v.emplace_back(a);

is deduced as

v.emplace_back<const std::uint32_t &>(a);

where the function argument is expected to be a std::uint32_t. Perfect match, no conversion necessary outside the system header. If you were to enable warnings within system headers, you could end up with a bunch of spurious warnings

To get an implicit conversion in your code, you need to force emplace_back to expect a std::uint16_t, which can be done via

v.emplace_back<const std::uint16_t &>(a);

This would implicitly convert a to std::uint16_t before calling emplace_back, triggering the compiler warning in the same way that push_back does.



Answered By - JaMiT
Answer Checked By - Pedro (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing