Hailiang Zhang
Hailiang Zhang

Reputation: 18870

How to include a declaration in the comma operator?

I have two simple testing lines:

cout<<(cout<<"ok"<<endl, 8)<<endl;

cout<<(int i(8), 8)<<endl;

The first line worked, but the second failed compilation with

error: expected primary-expression before 'int'

For some reason, I do need a declaration in the comma operator. To be more specific, I want to declare some variables, obtain their values, and assign them to my constant class members from the initialization list of my class constructor. Following shows my intentions. If not achievable using comma operator, any another suggestions?

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>

using namespace std;

void readFile(const string & fileName, int & a, int & b)
{
    fstream fin(fileName.c_str());
    if (!fin.good()) {cerr<<"file not found!"<<endl; exit(1);}
    string line;
    getline(fin, line);
    stringstream ss(line);
    try {ss>>a>>b;}
    catch (...) {cerr<<"the first two entries in file "<<fileName<<" have to be numbers!"<<endl; exit(1);}
    fin.close();
}

class A
{
    private:
        const int _a; 
        const int _b; 
    public:
        A(const string & fileName)
            :   
            _a((int a, int b, readFile(fileName,a,b), a)),
            _b((int a, int b, readFile(fileName,a,b), b)) 
        {   
            /*  
            int a, b;
            readFile(fileName,a,b);
            _a = a;_b = b;
            */
        }   

        void show(){cout<<_a<<" "<<_b<<endl;}
};

int main()
{
    A a("a.txt");
    a.show();
}

Upvotes: 1

Views: 2017

Answers (4)

John Dibling
John Dibling

Reputation: 101456

You cannot. This is unpossible in C++. The fact that you are trying to do this is also a code smell. Something's not right here.

I want to declare some variables, obtain their values, and assign them to my constant class members from the initialization list of my class constructor. Not sure how to achieve this.

You didn't say what you intended to do with these variables you declare after you've used the values, but I'm guessing that once you've finished with the values, you've finished with the variables. In other words, they are temporary.

Your edited example suggests that my assumption is correct. It also confirms the code smell. Based on your (intended) code, you are going to read the file twice.

I'd say the most straightforward way to do this is to use an intermediary, kind of like a factory class. This also has the benefit of being able to read the file only once, as opposed to twice as you are doing now.

void readFile (const std::string& fileName, int& a, int& b)
{
    // some magic
    a = 42;
    b = 314;
}

class FileReader
{
public:
    FileReader (const std::string fileName)
    :
        mFileName (fileName),
        mA (42),
        mB (314)
    {
        // something happens like reading the file
    }

    int GetA () const
    {
        return mA;
    }
    int GetB () const
    {
        return mB;
    }
private:
    int mA;
    int mB;
    std::string mFileName;
};

class A
{
private:
    const int mA;
    const int mB;
public:
    A (const FileReader& reader)
    :
        mA (reader.GetA()),
        mB (reader.GetB())
    {
    }
};

Using this FileReader is simple:

int main()
{
    A myA (FileReader ("somefile.txt"));
}

Upvotes: 4

aschepler
aschepler

Reputation: 72271

A lambda allows a declaration within an expression. So this is possible:

std::cout << ([]{ int i(8); m_i = i; }(), 8) << std::endl;

But it's really weird - I assume this will be in some #define macro that makes it appear closer to normal.

Upvotes: 5

sehe
sehe

Reputation: 392911

You should have a look at Boost Phoenix (which has phoenix::let to do roughly this). Bear in mind, Phoenix is an eDSL, really (embedded domain specific language).

You could do an ugly trick and abuse lambdas:

cout<< ([]->int{ int i(8); return 8; })() <<endl;

Upvotes: 5

templatetypedef
templatetypedef

Reputation: 372764

Declarations are statements and not expressions. You cannot place statements inside of expressions, though you can place expressions inside of statements. Accordingly, you cannot declare a variable in the way that you're describing above. You'll need to separate it out into multiple different statements.

I would be surprised if if you actually needed to do this. If you do, there is probably something problematic about your design.

Hope this helps!

Upvotes: 6

Related Questions