I'm looking at this code and found some peculiarities.
source: https://sourceforge.net/projects/bin2header/files/v0.4-test/bin2header-0.3.1.tar.xz/download
in the file: bin2header.cpp, you find the following code:
options.add_options()
("h,help", "")
("v,version", "")
("o,output", "", cxxopts::value<string>())
("n,hname", "", cxxopts::value<string>())
("s,chunksize", "", cxxopts::value<unsigned int>())
("d,nbdata", "", cxxopts::value<unsigned int>())
("c,datacontent", "")
("f,offset", "", cxxopts::value<unsigned long>())
("l,length", "", cxxopts::value<unsigned long>())
("p,pack", "", cxxopts::value<unsigned int>())
("e,swap", "")
("stdvector", "")
("eol", "", cxxopts::value<string>());
the function "add_options()" defined in "cxxopts.hpp" accepts multiple arguments with "(" and ")".
some contain 2 options and other contain 3.
How does that work?
i saw the usage of this: std::initializer_list
https://en.cppreference.com/w/cpp/utility/initializer_list
but the demonstrated example on CPP reference isdifferent.
Further more, cxxopts::value<string>(), this value<string>(), value + datatype between "<" and ">" followed by "()".
Also defined in "cxxopts.hpp":
template <typename T>
std::shared_ptr<Value>
value()
{
return std::make_shared<values::standard_value<T>>();
}
template <typename T>
std::shared_ptr<Value>
value(T& t)
{
return std::make_shared<values::standard_value<T>>(&t);
}
What the clue behind that?
The add_options member function returns an object of type OptionAdder. This has an overload for its operator(). That means it can be called like a function. The result of this call is a reference to the same OptionAdder object, so you can call it like a function, again:
// in OptionAdder:
OptionAdder& operator()(
const std::string& opts,
const std::string& desc,
const std::shared_ptr<const Value>& value
= ::cxxopts::value<bool>(),
std::string arg_help = ""
);
This member function can be called with two or three arguments instead of four because the last two are defaulted.
Related
I'm trying to understand the static cast as used in the Pybind11 docs here. Specifically, they use the syntax
static_cast<void (Pet::*)(int)>(&Pet::set)
Since I haven't seen this syntax before I'm strugling to interpret and apply to my own code so I was hoping somebody could explain what's going on here. Thanks
Edit - some context
I am creating Pybind11 bindings to an overloaded method that has two signatures, which only differ by const qualification. The class I am binding is a template so I am using this strategy to create the bindings
template<class T>
class Matrix {
public:
...
/**
* get the row names
*/
std::vector<std::string> &getRowNames() {
return rowNames;
}
/**
* get the row names (mutable)
*/
const std::vector<std::string> &getRowNames() {
return rowNames;
}
...
My version of the helper function described in that post is this:
template<typename T>
void declare_matrix(py::module &m, const std::string &typestr) {
using Class = ls::Matrix<T>;
const std::string &pyclass_name = typestr;
py::class_<Class>(m, pyclass_name.c_str(), py::buffer_protocol(), py::dynamic_attr())
.def(py::init<unsigned int, unsigned int>())
.def("getRowNames", static_cast<const std::vector<std::string>(ls::Matrix<T>::*)()>(&ls::Matrix<T>::getRowNames))
but the getRowNames line produces the following error:
Address of overloaded function 'getRowNames' cannot be static_cast to type 'const std::vector<std::string> (ls::Matrix<complex<double>>::*)()'
For anybody else reading this, the cast I was able to figure out thanks to the answer is:
static_cast< std::vector<std::string>& (ls::Matrix<T>::*)()>(&Class::getRowNames)
The meaning of:
static_cast<void (Pet::*)(int)>(&Pet::set)
static_cast<T_1>(T_2) means we're casting type 2 to type 1.
T_1:
(Pet::*) is a pointer to a class member of Pet (see https://stackoverflow.com/a/9939367/14344821 for a further discussion)
void (Pet::*)(int) is a pointer to a member function that takes an int parameter, returning a void
T_2
&Pet::set is the memory location of Pet::set
So basically, we're stating explicitly that we are setting the integer value.
Now we can bind the set functions to python (allowing us to set both age and name):
.def("set", static_cast<void (Pet::*)(int)>(&Pet::set), "Set the pet's age")
.def("set", static_cast<void (Pet::*)(const std::string &)>(&Pet::set), "Set the pet's name");
I'm working with a C++ code that I've found online. The creator of this code insists that this code works, but I cant get the code to compile and run no matter what I do. In particular, i'm getting two errors, which are:
no instance of function template "Defer" matches the argument list
TDefer<DoPkg::<lambda_cbb42bad95cffc2340696a1e41564dae>> Defer<DoPkg::<lambda_cbb42bad95cffc2340696a1e41564dae>>(T &)': cannot convert argument 1 from 'DoPkg::<lambda_cbb42bad95cffc2340696a1e41564dae>' to 'T&'
The portion of the code where the above two errors are occurring is as follows:
bool DoPkg(const wchar_t* pPath, const wchar_t* pOutputPath) {
std::map<int, FILE*> files;
int mainPackageIndex = LoadPackages(pPath, files);
auto defer = Defer([&files]() -> void{
for (auto it : files){
fclose(it.second);
}
});
//More Code here...
return true;
}
The function being called in the auto defer part is:
template<typename T> TDefer<T> Defer(T & callback){
return TDefer<T>(callback);
I have tried to search for fixes to these issues, but I can't figure out how to fix them.
Defer takes an non-const lvalue reference. Your lambda expression that you have in the call site creates a temporary object, and temporary objects can't bind to non-const lvalue references.
You either need to change Defer to be
template<typename T> TDefer<T> Defer(T && callback)
// or
template<typename T> TDefer<T> Defer(T callback)
// or no template and use
TDefer<std::function<void()>> Defer(std::function<void()> callback)
So it can accept lvalues and temporaries, or make the lambda an object and then pass it to Defer like
auto temp = [&files]() -> void{
for (auto it : files){
fclose(it.second);
}
};
auto defer = Defer(temp);
What is the best way to declare a method like this:
calc( string name, string arguments,
string lib,
string &output, string &error,
string finishInfo )
where every parameter is optional? User can pass name, arguments and error if needed; pass only finishInfo or pass all six arguments. Probably the most user friendly is being able to call:
calc( "my name", , "my library", , , );
but I don't know if it's possible to do without boost. I cannot overload, because I'd need to create 62 methods. My best idea is:
calc( string * name = NULL, string * arguments = NULL,
string * lib = NULL,
string * output = NULL, string * error = NULL,
string * finishInfo = NULL )
I'm changing everything to pointers, this way we need to call
calc( ptr_myName, NULL, ptr_myLib, NULL, NULL, NULL );
or
calc( string name = "", string arguments = "",
string lib = "",
...
calc( "", "",
"my library",
My experience with many arguments of the same type is that it quickly becomes a frustrating and unreadable mess as I try to remember their order. Other languages like Python have the option to name a parameter as you pass it into the function, but unfortunately we do not have such pleasantries in C++
A nice workaround is an argument struct. With public variables (or equivalent getter/setter functions, but I haven't usually found that to be necessary), the end user can set the desired fields in a legible manner before passing the struct into the function:
For example:
struct calc_args
{
string name;
string arguments;
string finish_info;
string output; // out arg
string finishInfo; // out arg
};
void calc(calc_args& arguments)
{
// ...
}
My suggestion will be to use a std::map<std::string, std::string> as your input.
calc(std::map<std::string, std::string> const& args) { ... }
Then, you are free to pass whatever you can.
You can use
calc({{"name", "my name"}, {"lib", "my library"}});
calc({{"lib", "my library"}});
As a relevant point of interest, variadic templates could work here:
template <typename T>
T DoStuff (T t) //Base case
{
//do stuff..
return t;
}
template <typename T, typename... Args>
T DoStuff(T t, Args... args) //Recursive case
{
return DoStuff(t + args...);
}
int main()
{
DoStuff(1,2,3,4,5); //Output: 15
}
This allows you to pass an unknown number of parameters into a function and recursively operate upon each.
Hello Guys so i want to code something in C++ that i have for C# but as there is no params object in C++ i need some help :P
Ok, so here's what i want to do:
static Int32 Procedure(UInt32 address, params Object[] parameters)
{
Int32 length = parameters.Length;
Int32 index = 0;
UInt32 count = 0;
UInt32 Strings = 0;
UInt32 Single = 0;
UInt32 Array = 0;
while (index < length)
{
if (parameters[index] is Int32)
{
WriteInt32(0x10050000 + (count * 4), (Int32)parameters[index]);
count++;
}
else if(paramaters[index] is String){ }.... // Thats just one thing i wanna use.. i've got more
..........
..........
}
return ReadInt32(0x000000);
}
so i need to figure out what type the parameter is + i wanna use an unknown amount of arguments and i have no idea how i would do this xD
I hope its clear and hopefully someone can Help me :3
Thx, Nico!
You can achieve something similar in C++ with variadic templates. Note that since C++ has no runtime reflection, it's not possible to dynamically get the type of any value: it can only be done at compile-time. Importantly, this also means that you cannot build a parameter list at runtime and pass it to the function without rolling out your own stuff to do it.
It is also arguably much more complicated than a C# equivalent (but then again, if C++ had all the strengths of C# with no weaknesses of itself, nobody would be using C#).
There may be other patterns, but the one I usually use looks like this (example with a print function):
template<typename... T>
void print_all_values(int value, T... values)
{
printf("%i ", value);
print_all_values(values...);
}
template<typename... T>
void print_all_values(double value, T... values)
{
printf("%g ", value);
print_all_values(values...);
}
template<typename... T>
void print_all_values(const char* value, T... values)
{
printf("%s ", value);
print_all_values(values...);
}
template<typename Unknown, typename... T>
void print_all_values(Unknown&& value, T... values)
{
printf("(can't print) ");
print_all_values(values...);
}
void print_all_values() {}
print_all_values(4, "hello world", 5.2, nullptr);
// prints: "4 hello world 5.2 (can't print)"
What happens here:
template<typename... T>
void print_all_values
This tells the compiler to create a distinct version of print_all_values for each different parameter type sequences it finds in my program.
void print_all_values(int value, T... values)
void print_all_values(double value, T... values)
void print_all_values(const char* value, T... values)
These differentiate the call per the first parameter. The idea here is that the function will only print its first parameter, then recursively call the template version with the remaining parameters:
{
printf("%s ", value);
print_all_values(values...);
}
At the end of the recursion chain, each parameter has been printed.
For my example print_all_values(4, "hello world", 5.2, nullptr), this is basically what would happen:
print_all_values(4, "hello world", 5.2, nullptr) -> the compiler uses print_all_values(4, ...), at runtime it'll do printf("%i", value), and the call at the end of the function becomes:
print_all_values("hello world", 5.2, nullptr) -> the compiler uses print_all_values("hello world", ...), at runtime it'll do printf("%s", value), and then:
print_all_values(5.2, nullptr) -> the compiler uses print_all_values(5.2, ...), printf("%g", value), then:
print_all_values(5.2, nullptr) -> the compiler can't find a suitable overload, so it falls back to the print_all_values(Unknown&& value, T... values) overload, does "(can't print)", and creates a call to print_all_values(), which does nothing.
The last overload:
template<typename Unknown, typename... T>
void print_all_values(Unknown&& value, T... values)
tells the compiler how handle any unknown type (in this case by printing (can't print)). Without this overload, we'd get a compile-time error if we tried to print an unknown type (because it all happens at compile-time, remember).
Did you already try a variadic template declaration like given in the following sample?
template<typename... Args>
static int32_t Procedure(uint32_t address, Args&&... parameters) {
// ...
}
C++ allows you to write functions accepting any number of parameters in the form of variadic template functions:
template<typename... ARGS>
void f( ARGS... args )
{
}
In that example, ARGS and args denote what is known as variadic packs. Neither are a template parameter or an function parameter, are just something that represents a set of template parameters, and a set of function parameters (Respectively).
So that are not parameters, are parameter packs, and then them cannot be manipulated directly. To use the content of a variadic pack, you have to expand the pack with an ellipsis.
Consider the example above: template<typename... ARGS> declares a variadic template with a variadic-pack named ARGS which represents a set of type template parameters.
In the next line, we expand that pack (ARGS...) to use that types as the types of the function argumments. That generates the variadic pack of function argumments args.
To use that argumments inside the function, you should expand args too. Since a pack is just a indetermined set of argumments, you can only use it in contexts where you use the hole set of argumments, in other words, you cannot access directly an specific element of the pack. For example:
template<typename... ARGS>
void f( ARGS... args )
{
f( args... ); //We call f() expanding the args pack of function parameters
//and passing the set of parameters to the function.
}
If you need to traverse the set of parameters in a pack (Which you would do in C# using the subscript operator on the params), you have to use the functional programming way of pattern matching and head-tail recursive list traversing:
template<typename HEAD , typename... TAIL>
void print( const HEAD& head , const TAIL&... tail )
{
std::cout << head << std::endl; //Do something with the head (Which is a
//normal function parameter)
print( tail... ); //Pass the tail to the next call
}
Note that function expects at least one parameter (A variadic template could be empty, but print() has one non-variadic parameter) . You should provide an overload with no parameters to act as base case (The case when there is no more argumments in the argumments list):
void print()
{
//Base case. Does nothing.
}
Now consider the signature of the print() function: Is a function which can take any number of parameters of any combination of types. In contrast to the C# (And Java) approach, storing the parameters in an array of an universal base class, and rely on polymorphism and casting), the C++ approach uses a statically-typed alternative, where the type of each function parameter is well determined at compile time.
I have one template function which will take a pointer type and i have instantiated it before calling.
i have written function with its dummy implementation as follows:
template<T>fun_name( const T *p )
{
//written functionality which will give me class name that i will store into string Variable
e.g. i got output like this string Var = "First_class" or string Var = "Second_class"
//Using this class name i will call one function of that class
if(Var == "Fisrt_class")
{
First_class::static_function_name(p);
}
if(Var == "Second_class")
{
Second_class::static_function_name(p);
}
}
and in global scope i instantiated this function for two variables as like below:
template<first_class>static_function_name(const First_class *)
template<Second_class>static_function_name(const Second_class *)
above code gives me error that
error: no matching function call in Second_class::static_function_class(const Fisrt_class*)
error: no matching function call in First_class::static_function_class(const Second_class*)
thanks in advance!
I think this :
template<typename T> // template<class T> is equally valid!
void fun_name( const T *p )
{
T::static_function_name(p);
}
is enough!
Two more errors is fixed in the above code:
Mention the keyword typename in template<T> in your code. You can also write template<class T> which is equally valid.
Mention the return type of the function template as well.
Your function template "calls" each of the static functions in each class. Even though program flow may never get to one of the calls, the compiler still has to figure out the code for each of them.
So when you instantiate:
template<first_class>fun_name(const first_class*)
the compiler tries to compile the entire function with T = first_class, which means at some point inside the function, it will try to compile the function call:
Second_class::static_function_name(p);
But since variable p is a pointer to first_class, the compiler doesn't find the function.
If you want conditional compilation, try specializing your function instead so the compiler only compiles the function call you intended for each type:
template <T> fun_name (const T* p);
template <> fun_name<first_class>(const first_class* p) {
first_class::static_function_name(p);
}
template <> fun_name<second_class>(const second_class* p) {
second_class::static_function_name(p);
}
Alternatively, you can use member functions which seem to be intended for what you are trying to do here. Then you can create objects and call the functions directly:
first_class f;
second_class s;
f.function();
s.function();
try changing to ,
template<typename T>
void fun_name( const T *p )
{
T::static_function_name(p);
}