Why double parameter constructor begins with an explicit keyword? - c++

My buddy and I have been recently reading leveldb source code. And we encounter this problem. In leveldb db/skiplist.h file, there is a constructor declaration:
explicit SkipList(Comparator cmp, Arena* arena);
I know explicit constructor with single parameter means no implicit type conversion for constructor parameter. But what does double parameters constructor with explicit keyword mean?
Is it new rule of C++11?
Thanks.

With C++11, you can use braced-init-lists in place of some other expressions, and that makes a difference. For instance, you can use them in return statements:
SkipList foo() {
return {{}, nullptr}; //does not compile with explicit constructor
return SkipList{{}, nullptr}; //compiles with or without explicit constructor
}

Related

Conversion operator and default constructor [duplicate]

Is there any good reason that an empty set of round brackets (parentheses) isn't valid for calling the default constructor in C++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
I seem to type "()" automatically everytime. Is there a good reason this isn't allowed?
Most vexing parse
This is related to what is known as "C++'s most vexing parse". Basically, anything that can be interpreted by the compiler as a function declaration will be interpreted as a function declaration.
Another instance of the same problem:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v is interpreted as a declaration of function with 2 parameters.
The workaround is to add another pair of parentheses:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Or, if you have C++11 and list-initialization (also known as uniform initialization) available:
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
With this, there is no way it could be interpreted as a function declaration.
Because it is treated as the declaration for a function:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
The same syntax is used for function declaration - e.g. the function object, taking no parameters and returning MyObject
Because the compiler thinks it is a declaration of a function that takes no arguments and returns a MyObject instance.
I guess, the compiler would not know if this statement:
MyObject object();
is a constructor call or a function prototype declaring a function named object with return type MyObject and no parameters.
You could also use the more verbose way of construction:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
In C++0x this also allows for auto:
auto object1 = MyObject();
auto object2 = MyObject(object1);
As mentioned many times, it's a declaration. It's that way for backward compatibility. One of the many areas of C++ that are goofy/inconsistent/painful/bogus because of its legacy.
From n4296 [dcl.init]:
[ Note: Since () is not permitted by the syntax for initializer,
X a(); is not the declaration of an object of class X, but the
declaration of a function taking no argument and returning an X. The
form () is permitted in certain other initialization contexts (5.3.4,
5.2.3, 12.6.2).
—end note ]
C++11 Link
C++14 Link
As the others said, it is a function declaration. Since C++11 you can use brace initialization if you need to see the empty something that explicitly tells you that a default constructor is used.
Jedi luke{}; //default constructor

what is different between default constructers and void constructers [duplicate]

Is there any good reason that an empty set of round brackets (parentheses) isn't valid for calling the default constructor in C++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
I seem to type "()" automatically everytime. Is there a good reason this isn't allowed?
Most vexing parse
This is related to what is known as "C++'s most vexing parse". Basically, anything that can be interpreted by the compiler as a function declaration will be interpreted as a function declaration.
Another instance of the same problem:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v is interpreted as a declaration of function with 2 parameters.
The workaround is to add another pair of parentheses:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Or, if you have C++11 and list-initialization (also known as uniform initialization) available:
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
With this, there is no way it could be interpreted as a function declaration.
Because it is treated as the declaration for a function:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
The same syntax is used for function declaration - e.g. the function object, taking no parameters and returning MyObject
Because the compiler thinks it is a declaration of a function that takes no arguments and returns a MyObject instance.
I guess, the compiler would not know if this statement:
MyObject object();
is a constructor call or a function prototype declaring a function named object with return type MyObject and no parameters.
You could also use the more verbose way of construction:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
In C++0x this also allows for auto:
auto object1 = MyObject();
auto object2 = MyObject(object1);
As mentioned many times, it's a declaration. It's that way for backward compatibility. One of the many areas of C++ that are goofy/inconsistent/painful/bogus because of its legacy.
From n4296 [dcl.init]:
[ Note: Since () is not permitted by the syntax for initializer,
X a(); is not the declaration of an object of class X, but the
declaration of a function taking no argument and returning an X. The
form () is permitted in certain other initialization contexts (5.3.4,
5.2.3, 12.6.2).
—end note ]
C++11 Link
C++14 Link
As the others said, it is a function declaration. Since C++11 you can use brace initialization if you need to see the empty something that explicitly tells you that a default constructor is used.
Jedi luke{}; //default constructor

Is the default constructor called differently when using parentheses versus nothing? (on a template class struct) [duplicate]

Is there any good reason that an empty set of round brackets (parentheses) isn't valid for calling the default constructor in C++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
I seem to type "()" automatically everytime. Is there a good reason this isn't allowed?
Most vexing parse
This is related to what is known as "C++'s most vexing parse". Basically, anything that can be interpreted by the compiler as a function declaration will be interpreted as a function declaration.
Another instance of the same problem:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v is interpreted as a declaration of function with 2 parameters.
The workaround is to add another pair of parentheses:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Or, if you have C++11 and list-initialization (also known as uniform initialization) available:
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
With this, there is no way it could be interpreted as a function declaration.
Because it is treated as the declaration for a function:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
The same syntax is used for function declaration - e.g. the function object, taking no parameters and returning MyObject
Because the compiler thinks it is a declaration of a function that takes no arguments and returns a MyObject instance.
I guess, the compiler would not know if this statement:
MyObject object();
is a constructor call or a function prototype declaring a function named object with return type MyObject and no parameters.
You could also use the more verbose way of construction:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
In C++0x this also allows for auto:
auto object1 = MyObject();
auto object2 = MyObject(object1);
As mentioned many times, it's a declaration. It's that way for backward compatibility. One of the many areas of C++ that are goofy/inconsistent/painful/bogus because of its legacy.
From n4296 [dcl.init]:
[ Note: Since () is not permitted by the syntax for initializer,
X a(); is not the declaration of an object of class X, but the
declaration of a function taking no argument and returning an X. The
form () is permitted in certain other initialization contexts (5.3.4,
5.2.3, 12.6.2).
—end note ]
C++11 Link
C++14 Link
As the others said, it is a function declaration. Since C++11 you can use brace initialization if you need to see the empty something that explicitly tells you that a default constructor is used.
Jedi luke{}; //default constructor

problem with initialization by default in class Assignment operator and vector in c++ [duplicate]

Is there any good reason that an empty set of round brackets (parentheses) isn't valid for calling the default constructor in C++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
I seem to type "()" automatically everytime. Is there a good reason this isn't allowed?
Most vexing parse
This is related to what is known as "C++'s most vexing parse". Basically, anything that can be interpreted by the compiler as a function declaration will be interpreted as a function declaration.
Another instance of the same problem:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v is interpreted as a declaration of function with 2 parameters.
The workaround is to add another pair of parentheses:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Or, if you have C++11 and list-initialization (also known as uniform initialization) available:
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
With this, there is no way it could be interpreted as a function declaration.
Because it is treated as the declaration for a function:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
The same syntax is used for function declaration - e.g. the function object, taking no parameters and returning MyObject
Because the compiler thinks it is a declaration of a function that takes no arguments and returns a MyObject instance.
I guess, the compiler would not know if this statement:
MyObject object();
is a constructor call or a function prototype declaring a function named object with return type MyObject and no parameters.
You could also use the more verbose way of construction:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
In C++0x this also allows for auto:
auto object1 = MyObject();
auto object2 = MyObject(object1);
As mentioned many times, it's a declaration. It's that way for backward compatibility. One of the many areas of C++ that are goofy/inconsistent/painful/bogus because of its legacy.
From n4296 [dcl.init]:
[ Note: Since () is not permitted by the syntax for initializer,
X a(); is not the declaration of an object of class X, but the
declaration of a function taking no argument and returning an X. The
form () is permitted in certain other initialization contexts (5.3.4,
5.2.3, 12.6.2).
—end note ]
C++11 Link
C++14 Link
As the others said, it is a function declaration. Since C++11 you can use brace initialization if you need to see the empty something that explicitly tells you that a default constructor is used.
Jedi luke{}; //default constructor

explicit non-single parameter constructor

Can anyone explain why does non-single parameter constructor marked as explicit compile?
As far as I understand this is absolutely useless keyword here, so why does this compile without error?
class X
{
public:
explicit X(int a, int b) { /* ... */}
};
In C++03, and in this particular case, it makes no sense for a two parameter constructor to be marked explicit. But it could make sense here:
explicit X(int i, int j=42);
So, marking a two parameter constructor with explicit does not have to be an error.
In C++11, this use of explicit would prevent you from doing this:
X x = {1,2};
Not entirely true.
In C++11, constructors with multiple arguments can be implicitly converted using brace initialisation.