My colleague ran into an unexpected issue with emplace_back
and I am trying to wrap my head around it. The following test.cpp
is a minimal example that reproduces the issue:
#include <vector>
class A {
public:
A(int /*unused*/, int /*unused*/) {}
};
int main() {
int foo = 5;
double bar = 4.5;
std::vector<A> a_vec{};
a_vec.emplace_back(foo, bar); // Not caught by either clang-tidy or gcc
A a{foo, bar}; // Gives compiler warning as expected
}
Compiling with g++ 8.3.0 yields the following warning:
$ g++ -std=c++11 test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:10:15: warning: narrowing conversion of ‘bar’ from ‘double’ to ‘int’ inside { } [-Wnarrowing]
A a{foo, bar}; // Gives compiler warning as expected
So the implicit conversion is caught when a simple object is constructed, but not when emplace_back
is called. Even when the keyword explicit
is added to the constructor, no warning is generated.
Is it possible in some way to get conversion warnings when using emplace_back
like this?
Changing the emplace_back
line to: a_vec.emplace_back(A(foo, bar))
does not generate a warning (even with the explicit keyword). The only way to get a warning seems to be using push_back
or calling the constructor outside/before the emplace_back
call:
#include <vector>
class A {
public:
A(int /*unused*/, int /*unused*/) {}
};
int main() {
int foo = 5;
double bar = 4.5;
std::vector<A> a_vec{};
A a{foo, bar}; // Gives compiler warning as expected
a_vec.emplace_back(a);
}
I have tried several compiler flags, e.g. -Wall -Wextra -Wpedantic -Werror -Wsystem-headers
, but none seem to help.
Looking at the documentation for emplace_back
did not directly help. The reason could be related to the usage of std::allocator_traits::construct
or std::forward
, but I am uncertain on how.
I mostly want to know if it is possible to get the warnings when calling emplace_back
.
Aucun commentaire:
Enregistrer un commentaire