C++ вызывающая функция в делегате конструктора

В C++11 конструктор может быть перенаправлен другому конструктору в списке инициализации.

Это нормально для вызова функции в списке инициализации, как в этом вопросе

Также нормально вызывать функцию в делегате конструктора?

Я попробовал код, как это:

#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;
}

Для приведенного выше кода, просто передайте ему пустой файл, он напечатает только один "Got" во время инициализации b.

================================================== =====================

Замена строки (argv[1]) на argv [1] заставляет его работать, есть идеи, почему?

1 ответ

Решение

Ответ на отредактированный вопрос


Проблема в первой строке в main, она рассматривается как объявление функции, а не как инициализация переменной, фактически, если бы вы скомпилировали ее с помощью clang, она бы предупредила вас об этом:

предупреждение: круглые скобки были устранены как объявление функции

Это связано с тем, что определено в § 6.8 Разрешение неоднозначности в стандарте (AKA Most досадный анализ) (выделено мной...):

В грамматике существует двусмысленность, связанная с выражениями-операторами и объявлениями: выражение-выражение с явным преобразованием типа в стиле функции (5.2.3) в качестве крайнего левого подвыражения может быть неотличимо от объявления, где первый декларатор начинается с ((. В этих случаях заявление является декларацией.

Рассмотрим следующий пример:

#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;
}

Ответ на оригинальный вопрос FWIW


Почему бы просто не попробовать?

Не должно быть никаких проблем, если вы не вызовете функцию, которая будет использовать члены, которые еще не инициализированы.

Например ( демо):

#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;
}
Другие вопросы по тегам