C++ 具有可变数量和常量变量类型的类的编程模型

C++ 具有可变数量和常量变量类型的类的编程模型,c++,C++,我之前的问题()得到了一个完美的答案,但现在我有了一个新的要求,答案似乎不再有效 假设我有一个包含几个常量变量的类: class Base { protected: const int a, b; public: Base(string file); }; 需要在初始化列表中初始化常量,但也需要提前使用其他方法来计算值 答案是使用助手类: class FileParser { public: FileParser (const string

我之前的问题()得到了一个完美的答案,但现在我有了一个新的要求,答案似乎不再有效

假设我有一个包含几个常量变量的类:

class Base
{
    protected:
        const int a, b;
    public:
        Base(string file);
};
需要在初始化列表中初始化常量,但也需要提前使用其他方法来计算值

答案是使用助手类:

class FileParser 
{
public:
  FileParser (const string& file)
  {
    Parse (file);
  }

  int GetA () const { return mA; }
  int GetB () const { return mB; }

private:
  int mA;
  int mB;

  void Parse (const string& file)
  {
    // MAGIC HAPPENS!
    // Parse the file, compute mA and mB, then return
  }
};
这完美地解决了我的问题,但是现在,如果我有一系列从Base派生的类,这些类具有不同数量和类型的常量,并且我想使用相同的helper(FileParser)类,那该怎么办呢?我不能使用Boost C++,但我有C++ 11。我尝试了使用变量返回长度可变的元组的模板,但这似乎并不简单。以下是我尝试过的修改过的帮助器类:

template <typename ... Types>
class LineParser
{
    private:
        std::tuple<Types...> _t; 
    public:
        LineParser(const std::string & line)
        {   
            // local variables
            std::stringstream ss; 

            // parse the line
            ss.str(line);
            for (int i=0; i<sizeof...(Types); i++)
            {   
                ss>>std::get<i>(_t);
            }   
        }   
};

我无法解决这个问题,我可能正在寻找一些替代解决方案。c++

所以这变得有点复杂。这也有点奇怪,但至少在这里你对X和Y都很清楚

让我们从您提出的方法开始。这是行不通的:

std::get<i>(_t);
这里有一个字符串、一个浮点和一个整数。不同的文件可能具有完全不同的数据,并且一个文件中给定位置的数据可能与不同文件中相同位置的数据的类型不同。然后,需要使用这些不同的文件初始化一组不同的类,每个类都有自己的不同类型的不同数据成员集合,这些数据成员来自文件中的不同位置。恶心

考虑到问题的复杂性,我自然倾向于尽可能简单地解决问题。这里已经有足够的复杂性了。我所能想到的最简单的方法就是为要解析的每种文件类型使用不同的具体
LineParser
类。然而,如果您有许多不同类型的文件,这将导致代码膨胀,并且随着文件数量的增加,维护变得越来越困难。让我们继续假设你不想那样做

但是,有一件事不会增加,那就是文件中不同类型字段的数量。最终,只有几个:字符串、整数、浮点数,也许还有一些特定于您的域的特殊内容。但是,即使添加更多数据文件,字段类型的数量也将保持相对恒定。另一个常量是文件本身:它是字符数据。让我们利用这一点

实现一些自由函数,将文件存储类型(这里假设为字符数据)转换为不同的字段。如果您使用的是Boost,那么可以使用
lexical\u cast
来完成大部分工作。否则,您可以使用
stringstream
或其他方法。以下是一个可能的实现,还有许多其他实现:

template <typename Return> Return As (const std::string& val)
{
  std::stringstream ss;
  ss << val;
  Return retval;
  ss >> retval;
  return retval;
}
现在在
Base
构造函数中,对于每个
const
数据成员,从
LineParser
中提取一个特定项,并使用自由函数将其转换:

class Base
{ 
private:
  const std::string mTicker;
  const uint32_t mSize;
  const float mPrice;
public:
  Base (const LineParser& parser)
  : 
    mTicker (As <std::string> (parser.GetAt (0))),  // We know the ticker is at field 0
    mPrice (As <float> (parser.GetAt (1))),  // Price is at field 1...
    mSize (As <uint32_t> (parser.GetAt (2))
  {
  }
};

例如,
mTicker
的初始值设定项表示“股票代码是一个字符串,它是从文件中的位置1提取的。”清除。

嘿,谢谢你的道具。)不能将tuple与变量一起使用来访问tuple元素。它是在编译时完成的。也许这个链接对你有帮助:啊,我陷入了XY问题!我知道现在花更多的时间让我的问题更广泛、更具体是多么重要。顺便说一句,提出的基于向量的方法工作得非常好!
template <typename Return> Return As (const std::string& val)
{
  std::stringstream ss;
  ss << val;
  Return retval;
  ss >> retval;
  return retval;
}
class LineParser
{
    private:
        std::vector <string> mItems;
    public:
        LineParser(const std::string & fileName)
        {   
          std::ifstream fs(fileName);
          std::copy(
            std::istream_iterator<int>(fs), 
            std::istream_iterator<int>(), 
            std::back_inserter(mItems));
        }   

        std::string GetAt (size_t i) const
        { 
          return mItems [i];
        }
};
class Base
{ 
private:
  const std::string mTicker;
  const uint32_t mSize;
  const float mPrice;
public:
  Base (const LineParser& parser)
  : 
    mTicker (As <std::string> (parser.GetAt (0))),  // We know the ticker is at field 0
    mPrice (As <float> (parser.GetAt (1))),  // Price is at field 1...
    mSize (As <uint32_t> (parser.GetAt (2))
  {
  }
};
 Base (const LineParser& parser)
 : 
   mTicker (As <std::string> (parser.GetAt (0))),  // We know the ticker is at field 0
   mPrice (As <float> (parser.GetAt (1))),  // Price is at field 1...
   mSize (As <uint32_t> (parser.GetAt (2))
 {
 }