I have the following code which is giving me this error
main.cpp(41): error C2664: 'std::pair std::make_pair(_Ty1,_Ty2)' : cannot convert argument 1 from 'Handle' to 'unsigned int &'
My example program is
#include <vector>
#include <utility>
typedef unsigned int u32;
typedef u32 Handle;
struct File
{
File()
: ch(0),
pageIdx(0)
{
}
Handle ch : 8;
u32 pageIdx;
};
int main() {
std::vector<std::pair<Handle, u32> > toTrim;
toTrim.reserve(64);
File* m_pFirstPage = new File();
File* pRef = m_pFirstPage;
toTrim.push_back(std::make_pair(pRef->ch,pRef->pageIdx));
return 0;
}
When I try to static cast i.e
toTrim.push_back(std::make_pair(static_cast<unsigned int>(pRef->ch), pRef->pageIdx));
I get the following error
main.cpp(41): error C2664: 'std::pair std::make_pair(_Ty1,_Ty2)' : cannot convert argument 1 from 'unsigned int' to 'unsigned int &'
Can someone please help me resolve it and explain what I am doing wrong.
What is happening is that you are specifying bit fields with the : 8 notation.
More info at:
http://www.tutorialspoint.com/cprogramming/c_bit_fields.htm
That creates a pseudo-char field on your handle variable of 8 bits instead of 32 as typedef u32 Handle defines. std::make_pair requires passing it's arguments by reference.
Since Handle ch : 8 is different type from Handle you can't pass it by reference because is considered undefined behavior cast a variable that is pass by reference.
More info at:
How to cast a variable member to pass it as reference argument of a function
If you need the : 8 field you may use an extra variable to create the pair correctly.
#include <vector>
#include <utility>
typedef unsigned int u32;
typedef u32 Handle;
struct File
{
File()
: ch(0),
pageIdx(0)
{
}
Handle ch : 8; //Different type than just Handle
u32 pageIdx;
};
int main() {
std::vector<std::pair<Handle, u32> > toTrim;
toTrim.reserve(64);
File* m_pFirstPage = new File();
File* pRef = m_pFirstPage;
unsigned int ch_tmp = pRef->ch; //<-Extra variable here
toTrim.push_back(std::make_pair(ch_tmp, pRef->pageIdx));
return 0;
}
Related
I have something like below, but unable to compile it. I don't get it why I can't have different type when my variable can hold different types?
My code:
#include <boost/variant.hpp>
#include <iostream>
typedef boost::variant<int, float, double, std::string> MultiType;
int main() {
int a = 1;
std::string b = "b";
bool c = true;
MultiType d = c ? a : b;
return 0;
}
The error:
Error C2446 ':': no conversion from 'std::string' to 'int'
The expression c ? a : b has to have a type. There is no common type between std::string and int, so that expression is invalid.
There is a common type between std::string and MultiType, and between int and MultiType, so c ? MultiType{ a } : b is a valid expression, as is c ? a : MultiType{ b }
Given the following mock method
MOCK_METHOD2(send, int(const void* pBuffer, size_t szBuffer));
And the following usage
EXPECT_CALL(socketMock, send(_, _))
.Times(1)
.WillOnce(ReturnArg<1>());
Will generate a warning in ReturnArg due to the implicit conversion of szBuffer into the return type of int.
Here's an example of code:
#include <cstddef>
#include <cstdint>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
class ISocket {
public:
virtual int Send(const uint8_t* payload, const std::size_t payloadLength, std::size_t& sentLength) = 0;
};
class SocketMock : public ISocket {
public:
MOCK_METHOD3(Send, int(const uint8_t*, const std::size_t, std::size_t&));
};
class MySender
{
public:
static void Ping(ISocket& socket)
{
std::size_t bytesSent;
uint8_t payload[64];
memset(payload, 0, sizeof(payload));
socket.Send(payload, sizeof(payload), bytesSent);
if (bytesSent != sizeof(payload))
throw std::runtime_error("Socket transmission failed");
}
};
TEST(SocketSend, ReturnsBytesTransmitted)
{
SocketMock socket;
EXPECT_CALL(socket,
Send(
::testing::_, // payload
::testing::_, // payload length
::testing::_ // return by param, bytes sent
)).Times(1)
.WillOnce(::testing::ReturnArg<1>());
MySender::Ping(socket);
::testing::Mock::VerifyAndClearExpectations(&socket);
}
GTEST_API_ int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Here's the compiler warning:
googletest\googlemock\include\gmock/gmock-more-actions.h(165): warning C4267: 'return': conversion from 'size_t' to 'int', possible loss of data (compiling source file TestMain.cpp)
Is there anyway to make GMock use a static_cast to change the return type to eliminate the type conversion warning?
ReturnArg<k> is a Google Mock "action" (reference) that returns the kth argument of the function being mocked. Since in this case, the return type of the function is int and the first argument is of type size_t, a warning about a potentially narrowing warning is generated.
The easiest way to inject an explicit typecast is to write a custom action:
ACTION_TEMPLATE(ReturnArgWithTypeCast,
HAS_2_TEMPLATE_PARAMS(int, k, typename, return_type),
AND_0_VALUE_PARAMS()) {
return static_cast<return_type>(::testing::get<k>(args));
}
The action can be used this way:
...
.WillOnce(ReturnArgWithTypeCast<1, int>())
How can I properly initialize a struct which contains a union? Currently I get an error // error C2440: 'initializing': cannot convert from 'float' to 'const char *'
#include <stdio.h>
using namespace std;
typedef enum {STRING, REAL, POINTER } Type;
const struct Entry {
union {
const char *string;
float real;
void *pointer;
};
Type type;
LPCSTR Key;
LPCSTR Name;
}f;
const Entry Entries[] = {
{{0.5f}, REAL, "Key", "Name" } // error C2440: 'initializing': cannot convert from 'float' to 'const char *'
};
int main(int argc, char **argv)
{
for (int i = 0; i < size(Entries); i++)
{
switch Entries[i].type
{
case STRING:
printf("Type string; Value: %s\n", Entries[i].string);
case REAL:
printf("Type string; Value: %d\n", Entries[i].real);
}
}
}
When initializing a union, only the first member will be initialized. Rearrange the union so that float real becomes the first member of the union.
Of course, that means you can't use the other members in direct initialization.
The other solution is to add a constructor to the union, like one for the real member, one for the string member and one for the pointer member.
What is the reason You want to use union? Unions are great for saving memory. In c++ rarely there is a need to use them.
I know that is not the answer for your question but think if You have to use them in this project.
I'm trying to set up some unit tests with QtTest and i'd like to use QFETCH.
I am testing the following function :
static std::vector<bool> FrameHandler::getBitsFromFrame(unsigned char* data, unsigned char length);
It simply converts a array of char into a vector of bits.
So, I set up my test class like this :
#include <QtTest/QtTest>
#include <vector>
#include "FrameHandler.h"
class BusTester : public QObject {
Q_OBJECT
private slots:
void bytesToVector_data() {
QTest::addColumn<unsigned char[]>("Tested");
QTest::addColumn<unsigned char>("Length");
QTest::addColumn< std::vector<bool> >("Reference");
// Test for one byte
std::vector<bool> oneByte(8, false);
oneByte[0] = true;
oneByte[1] = true;
oneByte[3] = true;
oneByte[4] = true;
unsigned char oneByteInput[1]{
0b11011000
};
QTest::newRow("One byte") << oneByteInput << 1 << oneByte;
}
void bytesToVector() {
QFETCH(unsigned char[], tested);
QFETCH(unsigned char, length);
QFETCH(std::vector<bool>, reference);
QCOMPARE(FrameHandler::getBitsFromFrame(tested, length), reference);
}
};
QTEST_MAIN(BusTester)
#include "bustester.moc"
When I do this, the compiler says :
expected unqualified-id before ‘[’ token
QFETCH(unsigned char[], tested);
And also :
On line `QTest::addColumn<unsigned char[]>("Tested");`, Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system
I thought the two errors were linked, so i added Q_DECLARE_METATYPE(unsigned char[]); before the class declaration, but then I get this :
In qmetatype.h, expected '>' before '*' token (line 1695)
Is it possible to declare unsigned char[] to Qt's QMetaType system ?
Thanks
Q_DECLARE_METATYPE(T) Type T must be constructable, copiable and destructable.
Array doesn match this rules, but you can create wrapper around.
struct Arr
{
unsigned char arr[SIZE];
};
Q_DECLARE_METATYPE( Arr );
or
typedef std::array<unsigned char, SIZE> TArr;
Q_DECLARE_METATYPE( TArr );
But there is one difficulties - SIZE, You have-to declare it
I have a function accept multiple arguments.
#include <iostream>
#include <cstdarg>
#include <vector>
using namespace std;
template<typename... Values>
void doSomething(size_t input, Values... inputs)
{
size_t len = sizeof...(Values) + 1;
size_t vals[] = {input, inputs...};
vector<size_t> n(len);
std::copy( vals, vals+len, n.data() );
for(size_t i=0; i<len; i++) cout<<n[i]<<endl;
//Do something with n vector
}
It works fine when I call this function by:
size_t a(1), b(2), c(3);
doSomething(a,b,c);
However, it will have a problem when I call this function by:
doSomething(1,2,3);
It will give out warning message:
warning: narrowing conversion of ‘inputs#0’ from ‘int’ to ‘size_t {aka long unsigned int}’ inside { } [-Wnarrowing]
size_t vals[] = {inputs...};
I do not like this warning message, is there a way to solve this problem? I would like the function to be able to accept either size_t or int. Thank you.