can someone explain me how's the argument passed in the 1st parameterized constructor working?
public:
//Constructors
Bigint();
Bigint(long long); // 1st parameterized constructor
Bigint(std::string); // 2nd parameterized constructor.
long long is a type, just like int or long. But the difference is that it's at least 64 bits wide.
See http://en.cppreference.com/w/cpp/language/types.
Related
I've read many text mentioned the in-class-initializer and I've searched many question on stackoverflow, However I didn't found any precise explanation on what is the in-class-initializer. And as far as I understood the variable of build-in type declared outside any function will be default initialized by the compiler, does the in-class-initilizer doing the same action for a declared variable?
Here is a simple example for in-class initialization. It's useful for less typing, especially when more than one constructor signatures are available. It's recommend in the core guidelines, too.
class Foo {
public:
Foo() = default; // No need to initialize data members in the initializer list.
Foo(bool) { /* Do stuff here. */ } // Again, data member already have values.
private:
int bar = 42;
// ^^^^ in-class initialization
int baz{};
// ^^ same, but requests zero initialization
};
As the data members are explicitly initialized, the second part of your questions doesn't really apply to to in-class initialization.
I am implementing a command pattern implementations with large number of actions and parameters involved. To simplify I am planning to use class that can hold all possible params to module in a map.
class ParamBag {
public:
add(int paramId, shared_ptr<IParam> param);
bool contains(int paramId);
std::shared_ptr<IParam> get(paramId);
private:
int mask;
std::map<int, std::shared_ptr<IParam>> params;
};
One clear downside of this implementation is each param has to extend from IParam interface, can I somehow simplify this.
If the one that uses the param after the get knows the type of the param, then you can use c++17 std::any, or if you must use c++11 you can try boost::any, or if none of those you can resort back to a void*.
The difference is that void* will not fail on a cast to a wrong type, where any_cast would throw an exception, or return nullptr if used with a pointer. You would also need to use a custom deleter in the std::shared_ptr in order to be able to free the void*.
Say we have
struct Test {
void foo(int *);
void foo(float);
} test;
Given the the following method call:
test.foo(1);
The compiler will resolve it by invoking Test::foo(float), doing the implicit conversion from int to float.
Is it possible to somehow get the signature of the thus resolved method overload as a pointer type, i.e. void (Test::*)(float)?
The closest thing to a positive answer I could get is the answer to another question, however that approach will fail in case of an implicit conversion of one or more parameters.
I have the following code which work fine. I am trying to understand the syntax. The return statement has std::plus<double>(). The double over here has the return value data type. But the function definition has the return type as std::function<double(double, double)> which indicates two double parameters. How do these two relate to each other?
#include <functional>
#include <iostream>
using namespace std;
std::function<double(double, double)> GetFunction()
{
return std::plus<double>();
}
int main()
{
auto operation = GetFunction();
int a = operation(1, 4);
std::cout << std::plus<>{}(1, 4) << '\n';
return 0;
}
There is an implicit conversion from std::plus<double> to std::function<double(double,double)>, because the former has a member call operator double operator()(double, double). See the documentation for std::function constructors.
In std::function<double(double, double)>:
The first double is the return type of the function. You can remember that by realizing that it's on the left, just like in a normal function definition.
The doubles in parentheses are the parameter types of the function, just like in a normal function definition; minus the parameter names. There are 2 since the plus function takes 2 doubles.
This makes sense if you think about it. The plus function/operator is a binary operator, meaning it takes 2 parameters of a type, and returns a single value of the same type. This is why you only need to specify a single type when you write std::plus<double>; the parameters and the return type must be the same type. It would be error prone and useless to force the caller to specify the same type 3 times.
If your question is, why there is only one double in the template parameter of std::plus but three in std::function, then the answer is this:
For std::plus, both parameters and the returntype always have to be the same, so you only have to specify it once.
std::function on the other hand can hold any function like object with any combination of parameters and returntypes, so you have to basically state each of those types individually.
I came across this article in which I read this example by one of the posters. I have quoted that here for convenience.
struct Foo
{
Foo(int i) {} // #1
Foo() {}
};
int main()
{
std::vector<Foo> f {10};
std::cout << f.size() << std::endl;
}
The above code, as written, emits “1” (10 is a converted to Foo by a
constructor that takes an int, then the vector’s initializer_list
constructor is called). If I comment out the line commented as #1, the
result is “10” (the initializer_list cannot be converted so the int
constructor is used).
My question is why does it emit a 10 if the int constructor is removed.
I understand that uniform initialization list works in the following order
1-Calls the initializer list if available or possible
2-Calls the default constructor if available
3-Does aggregate initialization
In the above case why is it creating 10 items in the vector since 1,2 and 3 are not possible ? Does this mean with uniform initialization a vector of items might always have different behaviors ?
Borrowing a quote from Scott Meyers in Effective Modern C++ (emphasis in original):
If, however, one or more constructors declare a parameter of type std::initializer_list, calls using the braced initialization syntax strongly prefer the overloads taking std;:initializer_lists. Strongly. If there's any way for compilers to construe a call using a braced initializer to be a constructor taking a std::initializer_list, compilers will employ that interpretation.
So when you have std::vector<Foo> f {10};, it will try to use the constructor of vector<Foo> that takes an initializer_list<Foo>. If Foo is constructible from an int, that is the constructor we're using - so we end up with one Foo constructed from 10.
Or, from the standardese, in [over.match.list]:
When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor
in two phases:
(1.1) — Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the
argument list consists of the initializer list as a single argument.
(1.2) — If no viable initializer-list constructor is found, overload resolution is performed again, where the
candidate functions are all the constructors of the class T and the argument list consists of the elements
of the initializer list.
If there is a viable initializer-list constructor, it is used. If you didn't have the Foo(int ) constructor, there would not be a viable initializer-list constructor, and overload resolution the second time around would find the constructor of vector that takes a size - and so you'd get a vector of 10 default-constructed Foos instead.