Как элегантно решить неоднозначные объявления в C ++ 11? - PullRequest
2 голосов
/ 11 апреля 2020
struct A
{
    A(int) {}
    A(std::initializer_list<int>) {}
};

template<typename T>
struct B
{
    B(A) {}
    B(std::initializer_list<T>) {}
};

int main()
{
    int n{};
    B   m1(A{n}); // error: call A::A(std::initializer_list<int>)
    B   m2(A(n)); // error: just a function declaration: B m2(A n);
}

Как показано в коде выше, я хочу вызвать B::B(A(int)) для создания объекта класса B. У меня есть два варианта:

  1. B m1(A{n});
  2. B m2(A(n));

Согласно C ++ Core Guidelines , первый Предпочтительный.

Однако, B m1(A{n}); будет вызывать A::A(std::initializer_list<int>) вместо A::A(int), что не предназначено. Итак, я должен использовать B m2(A(n));, но это просто объявление функции: B m2(A n);!

Как элегантно решить неоднозначные объявления в C ++ 11?

Ответы [ 3 ]

3 голосов
/ 11 апреля 2020

Символ почти всегда автоматически для спасения.

Я не уверен, что вы хотели, чтобы T был, так как это неясно в примере кода. Я использовал double, потому что ... почему бы и нет.

int main() {
    auto n = int{};
    auto m1 = B<double>(A{n});
    auto m2 = B<double>(A(n));
}

Отказ от ответственности: примерно половина разработчиков C ++, с которыми я общаюсь в реальной жизни (на работе), абсолютно презирает почти всегда автоматически, Мне это нравится (но я много сделал C# с var, F # и TypeScript, где все как обычно; и шаблон кода C ++ и lambda-with-auto), но есть много , кто яростно против авто. Если вы решите использовать почти всегда автоматически в своем собственном проекте, я настоятельно призываю вас обсудить это с коллегами и получить консенсус команды, прежде чем идти по этому пути.

3 голосов
/ 11 апреля 2020

Вы можете добавить другие скобки для аргумента A(n).

B m2((A(n)));
2 голосов
/ 11 апреля 2020

Как насчет ...

auto m1 = B(A(n));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...