LINUX.ORG.RU

Неочевидное поведение компилятора

 ,


0

2

Народ, выручайте - я в ступоре. Захотелось мне создать безымянный временный объект типа t, конструктор которого принимает строку, но не тут-то было!

#include <iostream>

struct t {
    t(const std::string & s) {
        std::cout << "t(): " << s << "\n";
    }
};

int main() {
  std::string s("string123");
  t(s);
}

 In function 'int main()':
11:6: error: conflicting declaration 't s'
10:15: note: previous declaration as 'std::string s'
http://cpp.sh/84qdi

Неужто парсер подавился на такой банальщине?


t(s);

Оно парсится как:

t s;
Синтаксис неоднозначен, выбрали вариант с объявлением для совместимости с C скорее всего.

xaizek ★★★★★
()
Ответ на: комментарий от Crocodoom

создать безымянный временный объект типа t

xaizek ★★★★★
()

А если это дело к войду кастануть?

То есть (void)t(s);

Crocodoom ★★★★★
()
Ответ на: комментарий от utf8nowhere

Не могли бы вы привести пруфы, показывающие банальность такого поведения компилятора?

Все предложенные решения хоть и рабочие, но пахнут сыростью и недоделанностью стандарта. Лично я нигде не встречал подобный стиль объявления переменных, но компилятор его почему-то поддерживает.

driver
() автор топика
Ответ на: комментарий от driver

Дата регистрации: 01.02.2018 22:46:25

Число комментариев: 1

И сразу — попытка вбросить в вентилятор.

Чёт тролли пошли нетерпеливые и унылые.

utf8nowhere ★★★
()
Последнее исправление: utf8nowhere (всего исправлений: 1)

Для чего может понадобиться такое поведение? В смысле, вызвать конструктор и... всё? Когда это надо? Правда интересно

anonymous
()
Ответ на: комментарий от anonymous

Для чего может понадобиться такое поведение? В смысле, вызвать конструктор и... всё? Когда это надо? Правда интересно

Вот тебе пример, когда нужно создавать временную переменную:

Например чтобы иметь потокобезопастный вывод в консоль...

using namespace std;

static mutex cout_mutex;

struct pcout : public stringstream
{
    ~pcout()
    {
        lock_guard<mutex> l {cout_mutex};
        cout << rdbuf();
        cout.flush();
    }
};

// тут где-то код pcerr, который использует тоже cout_mutex

int main()
{
    pcout() << "Hello, I'm thread safe" << '\n';
}

fsb4000 ★★★★★
()
Ответ на: комментарий от anonymous

Вот кусок из реального кода:

    auto invalidExmapleTest = [](const std::string & invalidExample) {
        bool testFailure = true;
        try { Blob(invalidExample); }
        catch(std::exception &) { testFailure = false; }
        return testFailure;
    };
Задача - спровоцировать исключение в конструкторе.

driver
() автор топика
Ответ на: комментарий от fsb4000

Например чтобы иметь потокобезопастный вывод в консоль

Он и так потокобезопасный.

http://eel.is/c++draft/iostream.objects#overview-5.sentence-1

Concurrent access to a synchronized ([ios.members.static]) standard iostream object's formatted and unformatted input and output functions or a standard C stream by multiple threads shall not result in a data race.

Лол!

utf8nowhere ★★★
()
Ответ на: комментарий от vvviperrr

(t(s));

Мне этот вариант по душе. Сам бы до такого не додумался.

driver
() автор топика
Ответ на: комментарий от utf8nowhere

Лол!

// 1.cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <sstream>
#include <vector>

using namespace std;

static void print_cout (int id)
{
    cout << "cout hello from " << id << '\n';
}



auto main() noexcept -> int
{
    try
    {
        vector<thread> v;

        for (size_t i {0}; i < 10; ++i)
        {
            v.emplace_back (print_cout, i);
        }

        for (auto& t : v)
        {
            t.join();
        }
    }
    catch (const exception& e)
    {
        cerr << "Exception: " << e.what() << endl;
    }
    catch (...)
    {
        cerr << "Unknown exception :(" << endl;
    }
}
g++-7 1.cpp -std=c++1z -O3 -pthread
./a.out 
cout hello from cout hello from 1
0cout hello from 
3cout hello from 4

cout hello from 2
cout hello from 5
cout hello from 6
cout hello from 7
cout hello from 8
cout hello from 9
fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от driver

Ага, я как-то сам писал похожий код. Вот только не помню, если у меня была такая проблема, как у ТС

anonymous
()
Ответ на: комментарий от anonymous

Пикантность моего кода в том, что компилятор на него ругался вот так:

No matching constructor for initialization of 'Blob'

Компилер пытался создать объект через дефолтный конструктор, когда мне нужно было протестировать конструктор с одним аргументом.

А всё потому, что я ленюсь следовать правилу трёх (пяти). А если бы следовал? Оно бы скомпилилось и всё стало бы еще запутаннее.

driver
() автор топика
Ответ на: комментарий от anonymous

Потому что у тебя была переменная, живущая до конца скопа, а у тс даже ее нет, и если это мутекс, то он в той же строке и разлочится.

anonymous
()

Неужто парсер подавился на такой банальщине?

Ох уж эти парсеры... Пишет их кто попало, а мы страдаем.

anonymous
()
Ответ на: комментарий от i-rinat

Прикольно, не работает) Мой вариант только для деклараций, кажущихся декларациями функций, видимо.

vzzo ★★★
()

Используй Basic... Или Pascal...

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.