In c++11, constructor can be forwarded to another constructor in the initialization list.
It is fine to call function in initialization list as in this question
Is it also fine to call function in the constructor delegate?
I tried code like this:
#include <iostream>
#include <string>
#include <yaml-cpp/yaml.h>
using namespace std;
YAML::Node ParseFromFile(const string& filepath) {
YAML::Node yaml;
try {
return YAML::LoadFile(filepath);
} catch(const YAML::BadFile& e) {
cout << "error";
}
}
class A {
public:
A(YAML::Node yaml) {
cout << "Got" << endl;
}
A(const string& filepath) : A(ParseFromFile(filepath)) {}
};
int main(int argc, char** argv) {
A a(string(argv[1]));
YAML::Node yaml = ParseFromFile(string(argv[1]));
A b(yaml);
return 0;
}
For the above code, just pass an empty file to it, it will only print one "Got" during the initialization of b.
=======================================================================
Replacing string(argv[1]) with argv[1] makes it work, any ideas why?
The problem is the first line in the main it's treated as a function declaration and not as a variable initialization, in fact have you compiled it with clang it would've give you a warning about this:
warning: parentheses were disambiguated as a function declaration
This is due what is defined in § 6.8 Ambiguity resolution in the standard (AKA Most vexing parse) (emphasis mine... ):
There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.
Consider the following example:
#include <iostream>
#include <string>
#include <exception>
using namespace std;
struct A{
string a;
A(string s) : a(s){ cout<< "Ctor" <<endl;}
A(int i) : A(to_string(i)){ }
};
void foo (A (*a)(string*)){
cout<<"yay"<<endl;
}
int main(int argc, char** argv) {
A a1( string(argv[1]) ); // function A a1(std::string*) declaration not a variable
/* ^ ^ ^
| | |
return type name arg type
Same as foo
*/
// foo(a1);// <- compiles but fails only due to linkage
A a2 = A(string(argv[1])); // works
A a3{string(argv[1])}; // works
A a4(string{argv[1]}); // works
A a5( ( string(argv[1]) ) ); // works allso but confusing imho
/* ^ ^
notice extra paren. | |
*/
return 0;
}
Why not just try?
There should be no problem unless you call a function that will use members that are still uninitialized.
E.g (demo):
#include <iostream>
#include <string>
using namespace std;
class A {
public:
A(string x) {
cout << "Got " << x << endl;
}
A(int x) : A(std::to_string(x)) {}
};
int main() {
A a(15);
return 0;
}