1

我有两条简单的测试线:

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

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

第一行有效,但第二行编译失败

error: expected primary-expression before 'int'

出于某种原因,我确实需要在逗号运算符中声明。更具体地说,我想声明一些变量,获取它们的值,并将它们从我的类构造函数的初始化列表中分配给我的常量类成员。以下显示了我的意图。如果使用逗号运算符无法实现,还有其他建议吗?

#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();
}
4

4 回答 4

6

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!

于 2013-07-17T19:10:27.400 回答
5

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.

于 2013-07-17T19:12:18.110 回答
5

你应该看看 Boost Phoenix (它有 phoenix::let 大致做到这一点)。请记住,Phoenix 实际上是一种 eDSL(嵌入式领域特定语言)。

你可以做一个丑陋的把戏并滥用 lambda:

cout<< ([]->int{ int i(8); return 8; })() <<endl;
于 2013-07-17T19:12:58.433 回答
4

你不能。这在 C++ 中是不可能的。您尝试这样做的事实也是代码异味。这里有点不对劲。

我想声明一些变量,获取它们的值,并将它们从我的类构造函数的初始化列表中分配给我的常量类成员。不知道如何实现这一点。

你没有说你打算在你使用这些值之后对你声明的这些变量做什么,但我猜一旦你完成了这些值,你就完成了这些变量。换句话说,它们是暂时的。

您编辑的示例表明我的假设是正确的。它还确认了代码气味。根据您的(预期)代码,您将读取该文件两次。

我想说最直接的方法是使用中介,有点像工厂类。这还具有只能读取一次文件的好处,而不是现在的两次。

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())
    {
    }
};

使用它FileReader很简单:

int main()
{
    A myA (FileReader ("somefile.txt"));
}
于 2013-07-17T19:32:01.750 回答