GoogleMock and QString argument - c++

I'm trying to use gmock with custom string type.
I have a method with QString argument which I want to mock:
MOCK_METHOD1(getValue, int(QString key));
I set an expectation:
EXPECT_CALL(mock, getValue("someKey"));
Got an error:
error: no matching function for call to 'MyMock::gmock_getValue(const char[8])'
include/gmock/gmock.h:9339:20: note: in definition of macro 'GMOCK_EXPECT_CALL_IMPL_'
((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
note: in expansion of macro 'EXPECT_CALL'
...
gmock/gmock.h:9730:7: note: no known conversion for argument 3 from 'const char [6]' to 'const testing::Matcher<const QString&>&'
gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
But this works:
EXPECT_CALL(mock, getValue(QString("someKey")));
How can I use string arguments without wrapping each string literal with QString() ?

It is due to "someKey" is not a QString, it is a const char[8] as reported by the error and Google Test / Mock requires that the 2 classes are the same.
In the same way a compiler does not know if the value 10 is supposed to be int32 int64, uint32 or uint64, the same applies.

Related

Problem of Compilation when defining factory for boost logger

Following the question asked here Boost.Log, using custom attributes in filename or target value of configuration file, I tried to develop the proposed solution but I encounter a build issue on Windows due to wchar_t vs char while trying to set the name of the files.
Error C2664 'boost::log::v2s_mt_nt6::basic_formatter<char>::result_type boost::log::v2s_mt_nt6::basic_formatter<char>::operator ()(const boost::log::v2s_mt_nt6::record_view &,boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &) const': cannot convert argument 2 from 'boost::log::v2s_mt_nt6::sinks::file::file_name_composer_adapter<boost::log::v2s_mt_nt6::basic_formatter<char>>::stream_type' to 'boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>> &'
file: boost\log\sinks\text_multifile_backend.hpp 107
stream_type being ostream of wchar_t due to Windows
if (boost::optional< std::string > param = settings["FileName"]) {
auto fmt = logging::parse_formatter((*param));
auto composer = sinks::file::as_file_name_composer(fmt);
backend->set_file_name_composer(composer);
}
How can I make parse_formatter works with wchar_t?
I also tried to use wchar_t as type of the sink_factory + std::wstring but it doesn't build either
Error C2664 'boost::log::v2s_mt_nt6::basic_formatter<wchar_t>::result_type boost::log::v2s_mt_nt6::basic_formatter<wchar_t>::operator ()(const boost::log::v2s_mt_nt6::record_view &,boost::log::v2s_mt_nt6::basic_formatting_ostream<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>> &) const': cannot convert argument 2 from 'boost::log::v2s_mt_nt6::expressions::aux::stream_ref<boost::log::v2s_mt_nt6::basic_formatting_ostream<char,std::char_traits<char>,std::allocator<char>>>' to 'boost::log::v2s_mt_nt6::basic_formatting_ostream<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t>> &'
file: boost\log\detail\light_function.hpp 362
supplying 'std::locale("en_US.UTF-8")' to the composer doesn't change anything as it's runtime
same remark for "expr::stream << expr::format(*param)" as formatter
I'm using boost_1_70_0
Do you know any solution?
Thanks!
parse_formatter returns basic_formatter<CharT>, where CharT is the character type deduced from the input argument. Thus, you will need to pass std::wstring in order to get wformatter which you can use with as_file_name_composer.
In order to get std::wstring parameter values from settings you will have to use wsettings, which you can obtain from parse_settings if you pass a std::wistream as input.

Cannot convert string to char* for argument 1

I am having an issue with my C++ code for converting a string of numbers in base b to another base n. My error is as follows:
cannot convert ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ to ‘char*’ for argument ‘1’ to ‘int base_to_decimal(char*, int)’
I am using g++ to compile, and I have been for a while, so I thought at first I knew what the issue was. It says that the method base_to_decimal accepts two arguments: one of type char* and one of type int. So all I should have to do to fix my issue is change the char* argument to a string, right?
Well, I looked, and the code for the function in question is:
int base_to_decimal(std::string input_base, int base)
So this method SHOULD be expecting a string, but for some reason when I pass in a string, it gets angry at me.
If someone could help me figure this out, that would be fantastic. I am using g++ 7.3.0, and running all this on Linux Mint 19.1.
(EDIT)
Main Method
Functions
Table
You've written a custom declaration on line 46 of your main:
int base_to_decimal(char * input_base, int base)
But in the functions file where you've defined your function, you have:
int base_to_decimal(std::string input_base, int base)
This is why you should not write in-line declarations for external functions, but instead put the declarations in a header file. #include in the file where the function is later defined, ensures that the definition matches the declaration that the other files are expecting. And likewise, it enforces that all those other files are trying to use the function the way it's actually coded.

Use a #define VALUE with a template

i cannot pass defined values to a template. Even a simple calculation doesnt work:
#define IR_TIMEOUT 564*173/2
return decodeSpace<IR_TIMEOUT>(
duration);
return decodeSpace<564*173/2>(
duration);
Working:
return decodeSpace<48786>(
duration);
The definition:
template <uint16_t irTimeout>
bool decodeSpace(unsigned long duration){}
The error:
E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp: In member function 'virtual bool IRLprotocolNEC::decodeIR(long unsigned int)':
E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp:46:11: error: no matching function for call to 'IRLprotocolNEC::decodeSpace(long unsigned int&)'
duration);
^
E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp:46:11: note: candidate is:
In file included from E:\Arduino\sketchbook\libraries\IRLremote/IRLprotocolNEC.h:27:0,
from E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp:24:
E:\Arduino\sketchbook\libraries\IRLremote/CIRLremote.h:103:9: note: template bool CIRLprotocol::decodeSpace(long unsigned int)
bool decodeSpace(unsigned long duration){
^
E:\Arduino\sketchbook\libraries\IRLremote/CIRLremote.h:103:9: note: template argument deduction/substitution failed:
E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp:46:11: error: overflow in constant expression [-fpermissive]
duration);
^
E:\Arduino\sketchbook\libraries\IRLremote\IRLprotocolNEC.cpp:46:11: note: in template argument for type 'unsigned int'
Is this a bug or a feature? Or better: How can i avoid/solve things like this?
I want to create different different decoding functions with the same structure but different timings. Passing the values takes a lot of flash so i better copy the function over and over. Thatswhy i wanted to use templates.
The problem is that 564*173 overflow uint16.
Use a define or a direct expression is the same thing when it comes for constant folding.
Constant folding is the fact that the compiler "expand" your expression. For example, replace "2*3" with "6".
The problem was that i needed to declare the calculation itself as long:
define IR_TIMEOUT 564UL*173/2
Thx # Matt McNabb

Convert from 'QChar' to 'wchar_t'

I need to pass a QChar to a function that expects a wchar_t:
void myFunc(wchar_t wch);
Trying to just pass the QChar fails with an error:
error: C2664: 'myFunc' : cannot convert parameter 1 from 'QChar' to 'wchar_t'
Found the answer even while I was asking the question, I needed to use QChar::unicode().
wchar_t wch = qch.unicode();

C++ in Ruby C extensions, pointer problems

I'm tryign to build a Ruby C extension that uses some c++ libraries. Problem is I can't even get a simple "hello world" to work.
//hello_world.cpp
#include <ruby.h>
static VALUE tosCore;
static VALUE my_function( VALUE self )
{
VALUE str = rb_str_new2( "Hello World!" );
return str;
}
extern "C"
void Init_hello_world( void )
{
tosCore = rb_define_module("Core");
rb_define_module_function(tosCore, "my_method", my_function, 0);
}
The output I get is
compiling hello_world.cpp
hello_world.cpp: In function 'void Init_hello_world()':
hello_world.cpp:17:67: error: invalid conversion from 'VALUE (*)(VALUE) {aka lon
g unsigned int (*)(long unsigned int)}' to 'VALUE (*)(...) {aka long unsigned in
t (*)(...)}' [-fpermissive]
In file included from c:/Ruby200/include/ruby-2.0.0/ruby.h:33:0,
from hello_world.cpp:2:
c:/Ruby200/include/ruby-2.0.0/ruby/ruby.h:1291:6: error: initializing argument
3 of 'void rb_define_module_function(VALUE, const char*, VALUE (*)(...), int)'
[-fpermissive]
make: *** [hello_world.o] Error 1
I'm no C/C++ expert. Ruby is my language. I have compiled a few thousand lines of C++ under Rice with no problem, but since I want this particular extension to compile under Windows, Rice is not an option.
It's because the function callback you present to rb_define_module_function is not what the compiler expects. It want a function looking like this:
VALUE my_function(...)
But your function is
VALUE my_function( VALUE self )
Notice the difference in the argument list.
One way to get rid of the error, is to type cast the argument to the type that rb_define_module_function expects:
rb_define_module_function(tosCore, "my_method",
reinterpret_cast<VALUE(*)(...)>(my_function), 0);
You can read about reinterpret_cast here.