Реализация C ++ эквивалента C # с помощью оператора - PullRequest
11 голосов
/ 03 февраля 2012

Я ищу элегантное решение для реализации эквивалента оператора C # с использованием C ++. В идеале результирующий синтаксис должен быть простым в использовании и чтении.

C # Подробности выписки здесь http://msdn.microsoft.com/en-us/library/yh598w02(v=vs.80).aspx

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

Ответы [ 6 ]

26 голосов
/ 03 февраля 2012

Вам не нужно реализовывать это в C ++, потому что стандартный шаблон RAII уже делает то, что вам нужно.

{
    ofstream myfile;
    myfile.open("hello.txt");
    myfile << "Hello\n";
}

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

Причина, по которой оператор using существует в C #, заключается в предоставлении некоторого синтаксического сахара вокруг try / finally и IDisposable. Это просто не нужно в C ++, потому что два языка различаются, и проблема решается по-разному на каждом языке.

3 голосов
/ 21 сентября 2014

Более подробный шаблон RAII, напоминающий оператор использования C #, может быть выполнен с помощью простого макроса.

#define Using(what, body) { what; body; }

Using(int a=9,
{
    a++;
})

a++; // compile error, a has gone out of scope here

Обратите внимание, что мы должны использовать заглавную "Using", чтобы избежать коллизии со встроенным в C ++ оператором using, который, очевидно, имеет другое значение.

3 голосов
/ 03 февраля 2012

Я бы взглянул на использование std :: auto_ptr <> для очистки всех экземпляров, выделенных и назначенных указателю в определенной области видимости - в противном случае любые переменные, объявленные в определенной области, будут просто уничтожены при выходеуказанная область действия.

{
    SomeClass A;
    A.doSomething();
} // The destructor for A gets called after exiting this scope here

{
    SomeClass* pA = new SomeClass();
    std::auto_ptr<SomeClass> pAutoA(pA);
    pAutoA->doSomething();
} // The destructor for A also gets called here, but only because we
  // declared a std::auto_ptr<> and assigned A to it within the scope.

См. http://en.wikipedia.org/wiki/Auto_ptr для получения дополнительной информации о std :: auto_ptr <>

1 голос
/ 18 марта 2018
    #define USING(...) if(__VA_ARGS__; true)

        USING(int i = 0)
        USING(std::string s = "0")
        {
            Assert::IsTrue(i == 0, L"Invalid result", LINE_INFO());
            Assert::IsTrue(s == "0", L"Invalid result", LINE_INFO());
        }
        //i = 1; // error C2065: 'i': undeclared identifier
        //s = "1"; //error C2065: 's': undeclared identifier
1 голос
/ 29 августа 2017

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

#include <iostream>

using namespace std;


class Disposable{
private:
    int disposed=0;
public:
    int notDisposed(){
        return !disposed;
    }

    void doDispose(){
        disposed = true;
        dispose();
    }

    virtual void dispose(){}

};



class Connection : public Disposable {

private:
    Connection *previous=nullptr;
public:
    static Connection *instance;

    Connection(){
        previous=instance;
        instance=this;
    }

    void dispose(){
        delete instance;
        instance = previous;
    }
};

Connection *Connection::instance=nullptr;


#define using(obj) for(Disposable *__tmpPtr=obj;__tmpPtr->notDisposed();__tmpPtr->doDispose())

int Execute(const char* query){
    if(Connection::instance == nullptr){
        cout << "------- No Connection -------" << endl;
        cout << query << endl;
        cout << "------------------------------" << endl;
        cout << endl;

        return -1;//throw some Exception
    }

    cout << "------ Execution Result ------" << endl;
    cout << query << endl;
    cout << "------------------------------" << endl;
    cout << endl;

    return 0;
}

int main(int argc, const char * argv[]) {

    using(new Connection())
    {
        Execute("SELECT King FROM goats");//out of the scope
    }

    Execute("SELECT * FROM goats");//in the scope

}
...