I always meet such a problem when coding.
there is a interface named "INetworkReader", which looks like:
struct INetworkReader
{
virtual void readFile(const std::string& url) = 0;
...
};
Now, I wanted to expand the readFile() function, the readFile() function need setting a timeout or something else to realize more controls, so Now I has two solutions.
solution 1(add a default parameter):
struct INetworkReader
{
virtual void readFile(const std::string& url, int timeout = 0) = 0;
...
};
solution 2(add another function):
struct INetworkReader
{
virtual void readFile(const std::string& url) = 0;
virtual void readFileTimeout(const std::string& url,int timeout) = 0;
...
};
I prefer the solution 1 for that it's parameter describe it's action clearly, the only disadvantage I think is that it increase the number of parameter.
So, as you see, which looks better? why?
I found another case which could be more complicated, look the following code.
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
}
Now want to add a parameter to tell if it's adding to a USB port, these are still has two solutions.
solution 1(add a default parameter):
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse, /* in */ bool USBPort = true ) = 0;
}
solution 2(add another function):
struct IComputer
{
virtual bool addMouse(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
virtual bool addMouseNotUSB(/* in */const std::string& mouseID, /*out*/ IMouse** ppMouse ) = 0;
}
this time I prefer the second for that the first solution has broken sequence of in-out parameter.
so, two case, four solutions, which one is better? why?
IMO I prefer solution 2 (as long as it takes a timeout parameter). If you face the code for the first time, you'll quickly understand what '1000' is in the expression readFileTimeout(url, 1000), rather than in readFile(url, 1000). In the second expression one could think the code is reading 1000 bytes, for example.
In the second case, I also prefer using different function names, but since we're passing a boolean, I'd use function names from which one can deduce the boolean value:
addMouse(const std::string& mouseID, IMouse** ppMouse) //For non-USB mice
addUSBMouse(const std::string& mouseID, IMouse** ppMouse) //For USB mice
The decision of using inverse logic or not (i.e. creating addNonUSBMouse instead of addUSBMouse) is arbitrary and depends on the cases your code is likely going to run. If in most cases mice are not USB, use my proposal. Otherwise use the inverse logic version.
My lemma is: try naming functions the way it would be unnecessary to read their prototypes.
Yet another option is to use types to force expressiveness in the calling code:
struct INetworkReader
{
virtual void readFile(const std::string& url, Timeout timeout = Timeout::Infinite) = 0;
...
};
Calling code might be:
p->readFile(url, Timeout{200, Timeout::ms});
Mote that a Timeout of 0 is a bit ambiguous: it might mean a non-blocking check for data, or it might block indefinitely, so a value like Infinite or Never is clearer.
With C++14 you could create an explicit Timeout constructor from a std::chrono::duration such as 200ms.
For the mouse example:
enum Connection { USB, NonUSB };
virtual std::pair<bool, IMouse*> addMouse(const std::string& mouseID,
Connection connection = USB ) = 0;
Notice that for the in / out parameter problem, I've returned all outputs rather than taking an IMouse**? You could return a tuple, pair or custom struct.
Solution 1 is preferred. It's definitely OK for a function to contain two parameters. Just consider other solutions(such as the Builder Pattern for too many parameters for constructors) when there are too many parameters.
Related
Similar questions have been asked before, such as String literal matches bool overload instead of std::string.
But what I want to know is what should C++ developers do to prevent this from happening? As someone who writes C++ libraries for others to consume, what should I do to ensure this doesn't happen? Here is the example I ran into today, where a library had 2 initialize() methods:
void initialize(bool someflag) { /* ... */ }
void initialize(const std::string & name) { /* ... */ }
Now the problematic code was in the application that wanted to utilize this functionality and which called it in a manner similar to this:
initialize("robert");
At first glance you'd think that this would call initialize(string) but it actually calls the first initialize(bool) with a boolean flag set to true!
Yes, I know it can be fixed with this:
initialize( std::string("robert") );
But this puts the onus on the caller.
Edit for #zdan: I didn't consider the "solutions" in the other linked question to be great solutions since 1) I was hoping not to have to add a const char * version of every method that takes a bool or string, and 2) the template solution increases the maintainability of the code significantly for affected methods, renders them almost unreadable.
what should I do to ensure this doesn't happen?
One possibility is to create an overload that accepts a char const* and make it a pass through to the overload that accepts a std::string.
void initialize(char const* name) { initialize(std::string(name)); }
I recently read Clean Code, and one concept they discouraged was passing variables that signal behavior into functions (i.e. a flag, if TRUE, do one thing, if FALSE, do another). The book says instead you should write two functions.
At the same time, duplicating chunks of code isn't ideal.
I've written a simple plaintext brute force password cracker (for a school project), which prints out each password.
I'd like a way to turn off the print portion of the code, so the user has the option of running it with printing or without (to decrease runtime).
My initial solution was like this:
bool bruteForce(bool printFlag)
{
for (all letter combinations)
if (printFlag)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
}
However, if I do this it might run slower. Maybe it won't make much of a difference and I'm overthinking it?
What would best practices be in this situation? Use a flag or make a separate function with print functionality?
There are many different opinion on subject like this.
My understanding from the book, is that you should avoid function with bolean parameter in such situation:
void module(bool enable) // Bad
// Good:
void enableModule();
void disableModule();
this is mostly a question of readability.
You should avoid duplicating code, in your situation, depending the rest of the structure of your class, perhaps you can have a class variable to enable / disable the flag printing as a separate function:
class x {
public:
bool bruteForce();
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
m_printFlag = false;
}
Depending the rest of your code, you can make bruteForce itself as a class with all the parameters it can have.
class BruteForce {
public:
bool start();
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
m_printFlag = false;
}
used as
BruteForce bf;
bf.enableFlagPrinting();
bf.start();
However, if I do this it might run slower. Maybe it won't make much of a difference and I'm overthinking it?
Given it's only an additional bool comparison, this is performed very fast and I doubt it will make any significant difference compared to the rest of the code, although you could duplicate code if it is really necessary, as long as it is well encapsulated:
class BruteForce {
public:
bool start()
{
if (m_printFlag) bruteForceWithFlags();
else bruteForceWithoutFlags();
}
void enableFlagPrinting() { m_printFlag = true; }
void disableFlagPrinting() { m_printFlag = false; }
private:
void bruteForceWithFlags();
void bruteForceWithoutFlags();
m_printFlag = false;
}
it's a trade-off speed / maintenability, from experience I suggest you to go for the maintenability :P.
If you are mainly concerned about performance, start reconsidering where you put your if:
bool bruteForce(bool printFlag) {
for (all letter combinations)
if (printFlag)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
}
What about this:
bool bruteForce(bool printFlag) {
if(printFlag)
for (all letter combinations)
fwrite(pw, sizeof(char), sizeof(pw) - 1, stdout);
...
else
for (all letter combinations)
...
}
How many times is the if potentially evaluated now? 1 vs #(all letter combinations).
This won't improve your performance so as they are acceptable, anyway.
Once you did it, if the ... part is long, put it in a separate function band do not repeat the code. Don't care of it if it's one line.
Finally, if you want to remove the boolean flag, well, add a second function. That's not a problem at all.
I prefer to add null-ostream discarding
#include <iostream>
#include <string>
#include <algorithm>
int
main(int argc, char* argv[]) {
bool verbose = true;
std::ostream out(0);
if (verbose)
out.rdbuf(std::cout.rdbuf());
out << "hello" << std::endl;
return 0;
}
I need to register functions like the following in a list of functions with arguments.
void func1( int a , char* b ) {}
void func2( vec3f a , std::vector<float> b , double c) {}
...
And call them back when I receive data over network with proper arguments. I imagined va_list would solve, but it doesnt work :
void func1(int a, char* b)
{
printf("%d %s",a,b);
}
void prepare(...)
{
va_list argList;
int args = 2;
va_start(argList, args);
((void (*)(va_list))func1)(argList);
va_end(argList);
}
int main(int argc, char **argv)
{
prepare(1, "huhu");
return 0;
}
What is the most elegant way to solve this ?
I know std::bind / std::function has similar abilities, but the internal data is hidden deep in std I assume. I just need a few basic data types, doesnt have to be for arbitrary types. If preprocessor tricks with ##VA_ARGS or using templates would solve, I am also OK with that. Priority is that it is most simple to use.
Edit1 : I found that assembly can solve ( How do I pass arguments to C++ functions when I call them from inline assembly ) - but I would prefer a more platform independent solution.
If your goal is to create your own, small and ad-hoc "rpc" solution, possibly one of the major drivers for making decisions should be: 1. Minimal amount of code 2. Easy as possible.
Keeping that in mind, it is paying off to ponder, what the difference is between the following 2 scenarios:
"Real" RPC: The handlers shall be as you wrote with rpc-method-specific signature.
"Message passing": The handlers receive messages of either "end point-determined type" or simply of a unified message type.
Now, what has to be done to get a solution of type 1?
Incoming byte streams/network packets need to get parsed to some sort of message with regards to some chosen protocol. Then, using some meta-info (contract), according to { serviceContract, serviceMethod }, a specific set of data items needs to be confirmed in the packet and if present, the respective, registered handler function needs to be called. Somewhere within that infrastructure you typically have a (likely code generated) function which does something like that:
void CallHandlerForRpcXYCallFoo( const RpcMessage*message )
{
uint32_t arg0 = message->getAsUint32(0);
// ...
float argN = message->getAsFloat(N);
Foo( arg0, arg1, ... argN );
}
All that can, of course also be packed into classes and virtual methods with the classes being generated from the service contract meta data. Maybe, there is also a way by means of some excessive template voodoo to avoid generating code and having a more generic meta-implementation. But, all that is work, real work. Way too much work to do it just for fun. Instead of doing that, it would be easier to use one of the dozens technologies which do that already.
Worth noting so far is: Somewhere within that piece of art, there is likely a (code generated) function which looks like the one given above.
Now, what has to be done to get a solution of type 2?
Less than for case 1. Why? Because you simply stop your implementation at calling those handler methods, which all take the RpcMessage as their single argument. As such, you can get away without generating the "make-it-look-like-a-function-call" layer above those methods.
Not only is it less work, it is also more robust in the presence of some scenarios where the contract changes. If one more data item is being added to the "rpc solution", the signature of the "rpc function" MUST change. Code re-generated, application code adapted. And that, whether or not the application needs that new data item. On the other hand, in approach 2, there are no breaking changes in the code. Of course, depending on your choices and the kind of changes in the contract, it still would break.
So, the most elegant solution is: Don't do RPC, do message passing. Preferably in a REST-ful way.
Also, if you prefer a "unified" rpc message over a number of rpc-contract specific message types, you remove another reason for code bloat.
Just in case, what I say seems a bit too abstract, here some mock-up dummy code, sketching solution 2:
#include <cstdio>
#include <cstdint>
#include <map>
#include <vector>
#include <deque>
#include <functional>
// "rpc" infrastructure (could be an API for a dll or a lib or so:
// Just one way to do it. Somehow, your various data types need
// to be handled/represented.
class RpcVariant
{
public:
enum class VariantType
{
RVT_EMPTY,
RVT_UINT,
RVT_SINT,
RVT_FLOAT32,
RVT_BYTES
};
private:
VariantType m_type;
uint64_t m_uintValue;
int64_t m_intValue;
float m_floatValue;
std::vector<uint8_t> m_bytesValue;
explicit RpcVariant(VariantType type)
: m_type(type)
{
}
public:
static RpcVariant MakeEmpty()
{
RpcVariant result(VariantType::RVT_EMPTY);
return result;
}
static RpcVariant MakeUint(uint64_t value)
{
RpcVariant result(VariantType::RVT_UINT);
result.m_uintValue = value;
return result;
}
// ... More make-functions
uint64_t AsUint() const
{
// TODO: check if correct type...
return m_uintValue;
}
// ... More AsXXX() functions
// ... Some ToWire()/FromWire() functions...
};
typedef std::map<uint32_t, RpcVariant> RpcMessage_t;
typedef std::function<void(const RpcMessage_t *)> RpcHandler_t;
void RpcInit();
void RpcUninit();
// application writes handlers and registers them with the infrastructure.
// rpc_context_id can be anything opportune - chose uint32_t, here.
// could as well be a string or a pair of values (service,method) or whatever.
void RpcRegisterHandler(uint32_t rpc_context_id, RpcHandler_t handler);
// Then according to taste/style preferences some receive function which uses the registered information and dispatches to the handlers...
void RpcReceive();
void RpcBeginReceive();
void RpcEndReceive();
// maybe some sending, too...
void RpcSend(uint32_t rpc_context_id, const RpcMessage_t * message);
int main(int argc, const char * argv[])
{
RpcInit();
RpcRegisterHandler(42, [](const RpcMessage_t *message) { puts("message type 42 received."); });
RpcRegisterHandler(43, [](const RpcMessage_t *message) { puts("message type 43 received."); });
while (true)
{
RpcReceive();
}
RpcUninit();
return 0;
}
And if RpcMessage then is traded, while packed in a std::shared_ptr, you can even have multiple handlers or do some forwarding (to other threads) of the same message instance. This is one particularly annoying thing, which needs yet another "serializing" in the rpc approach. Here, you simply forward the message.
I am wondering if there is a better way to write this for better readability.
If you have a function like below,
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
When you call the function, you will end up with something like
animal(true, false, true);
and this makes me go take a look at the definition every time I encounter function like this.
SO...
I do something like this!
const bool HAS_FOURLEGS = true;
const bool NO_HEAD = false;
const bool HAS_BODY = true;
animal(HAS_FOURLEGS, NO_HEAD, HAS_BODY);
But I do not like to declare const bool every time I call the function.
It seems like CPP does not support something like
animal(bool hasFourlegs = true, bool hasHead = false, bool hasBody = true);
Is there any better and shorter way?
When I run into issues related to this I sometimes create an enum even when there are only 2 expected choices:
For example, instead of the following function declaration:
bool search(..., bool recursive);
I'd go with:
enum class SearchOpt
{
Recursive,
NonRecursive
};
bool search(..., SearchOpt opt);
Therefore, the calling syntax changes from:
bool found = search(..., true);
to:
bool found = search(..., SearchOpt::Recursive);
Note: this avoids you having to create your own constants every time you call the function.
Edit
As others have suggested, instead of having separate bools for each option and thereby a separate enum for each it would make sense to have a single enum configured as bit flags.
Use flags:
enum {
HAS_LEGS = 0x01,
HAS_HEAD = 0x02,
HAS_BODY = 0x04,
};
void animal(int properties);
animal(HAS_LEGS | HAS_HEAD);
One other option is to use a class to hold the parameters where they're closely related:
struct AnimalOptions {
bool hasHead, hasBody, hasLegs;
AnimalOptions() : hasHead(false), hasBody(false), hasLegs(false);
}
...
AnimalOptions opt;
opt.hasHead = true;
animal(opt);
This technique is useful whenever you have a function which seems to take a bunch of parameters with identical types, whose order isn't easily remembered. It's just as useful when your function take several ints.
As a alternative to the other answers, I liked tagged_bool that Andrzej Krzemieński came up with on his blog.
Strange no one suggested named parameters from Boost.parameter: http://www.boost.org/doc/libs/1_59_0/libs/parameter/doc/html/index.html
Comments are your friends!
animal( true, //hasFourLegs
false, //hasHead
true //hasBody
);
You could use bitwise values, as follows:
const int hasLegs = 0x01;
const int noHead = 0x02;
const int hasBody = 0x04;
Then call animal with any combination of the above, e.g.:
animal(hasLegs + hasBody);
Decalre animal with a single int parameter.
inside `animal`, test the bits:
if (parameter & haasBody)
{
// it has a body....
}
C++20 has designated initializers as part of aggregate initialization. You could make a struct with the boolean parameters and pass the struct by value. You can even have default parameter values.
struct AnimalParts {
bool hasFourLegs = false;
bool hasHead = true;
bool hasBody = true;
}
void animal(AnimalParts parts);
Then use it like this:
animal({.hasFourLegs = true, .hasHead = false});
This comes very close to the named parameters idiom you suggested. In terms of compilation both options seem to produce comparable output, see on Godbolt.
I'm not sure it's a correct way to go, but still I cannot resist sharing this thought.
Let's imagine the function is not yours, but rather from some popular API which is hard to change.
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
In this case it's possible to call it like this:
animal(bool("hasFourlegs"), !bool("hasHead"), bool("hasBody"));
The C-string is always a non zero pointer, which is converted to true.
One possible downside is compilation time...?
Another is increase in length of code rows...
This is my first time posting my own question, so sorry if I break etiquette or something in some way. Most of the software in this program I'm working on wasn't coded by me. I'm wanting to create a thread using one of their functions.The function I want to implement in the thread looks like this. If possible I would like to be able to continue using pthreads:
void * bpsk_continuous(
uhd::usrp::multi_usrp::sptr usrp,
const std::string &cpu_format,
const std::string &wire_format,
const std::string &file,
size_t samps_per_buff,
unsigned long long num_requested_samples,
double time_requested = 0.0,
bool bw_summary = false,
bool stats = false,
bool null = false,
bool enable_size_map = false,
bool continue_on_bad_packet = false
){//operations of function}
Later they use syntax very unfamiliar to me that I'm assuming defines the arguments in some way. My first question would be what is the following code doing.
#define bpsk_continuous_args(format) \
(usrp, format, wirefmt, file, spb, total_num_samps, total_time, bw_summary, stats, null, enable_size_map, continue_on_bad_packet)
//if (type == "float") recv_to_file<std::complex<float> >recv_to_file_args("fc32");
My second question would be how can I create a thread that runs the bpsk_continuous argument given the syntax above. I tried the following but no dice:
pthread_t t1;
pthread_create(&t1, NULL, bpsk_continuous,bpsk_continuous_args("fc32"));
You should create auxiliary struct, and the start routine, lets say:
struct bpsh_args {
uhd::usrp::multi_usrp::sptr usrp;
std::string cpu_format;
std::string wire_format;
std::string file;
size_t samps_per_buff;
unsigned long long num_requested_samples;
double time_requested;
bool bw_summary;
bool stats;
bool null;
bool enable_size_map;
bool continue_on_bad_packet;
};
In the start routine you should cast it's only argument back to bpsh_args:
void* start_routine(void* _args) {
bpsh_args* args = static_cast<bpsh_args*>(_args);
bpsk_continuous(args->usrp, args->cpu_format, ...);
}
Then fill bpsh_args with appropriate data and then pass the pointer to it as last argument of pthread_create, and start_routine as one before last.
bpsh_args _bpsh_args;
_bpsh_args.usrp = ....;
_bpsh_args.cpu_format = "fc32";
...
pthread_create(&t1, NULL, start_routine, &_bpsh_args);
Consult man or http://man7.org/linux/man-pages/man3/pthread_create.3.html for details.
Be aware of the fact that after a new thread is started the struct with arguments is shared between two threads and the _args will be invalid if the variable _bpsh_args goes out of scope. Maybe you should better allocate it on heap, or add some synchronisation primitives to ensure that _bpsh_args is alive as long as you use it in descendant thread.
To answer your first question, what the #define does, it is a so-called macro. Macros just perform text replacement. Just do a little research and you will find out more about them, in particular that they are generally considered an evil feature of C++.
Then, if you need to rule out using a portable approach like std::thread (or even Boost's variant thereof), try this approach:
void* thread_function(void* arg)
{
assert(arg);
std::string const& format = *static_cast<std::string*>(arg);
return bpsk_continuous bpsk_continuous_args(format);
}
somewhere()
{
std::string format = ...;
pthread_create(.., &thread_function, &format, ..);
}
Note that this library is from what I can tell shoddy C++. The use of lower-case macros. Using them to work around its own overly long parameter lists. The seeming lack of understanding for namespaces. These all seems like a poor design choices to me and I wouldn't be surprised to find more of them.