How to include a declaration in the comma operator? - c++

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

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!

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;

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.

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"));
}

Related

Pass enum in a scope to another as function argument

How to pass enum in a scope to another as function argument? As this is failing:
enum class L;
struct TestClass
{
void foo(L n)
{
int v = static_cast<int>(n);
int r[v] = { 9 };
cout << "\n" << v << "\n";
}
};
int main()
{
enum class L : int
{
A, B, C, D
};
TestClass main;
main.foo(L::D);
return 0;
}
error: cannot convert ‘main()::L’ to ‘L’
80 | main.foo(L::D);
| ~~~^
| |
| main()::L
How to solve this (in exact place, not move enum to a scope else) ?
How to solve this (in the exact place, not move enum to a scope else)?
Cast the enum while passing as a parameter.
main.foo(static_cast<int>(L::D));
Then your member function would be
void foo(int n)
{
std::vector<int> r(n, 9); // used `std::vector` instead of VLA
std::cout << "\n" << n << "\n";
}
(See sample code)
Note that the VLAs are not part of standard C++. Read more in the following post:
Why aren't variable-length arrays part of the C++ standard?
Prefer using std::vector as shown in the above code sample.
In a nutshell, the problem is that you have an enum that you want to use in two places. To me, the most natural solution to this is to put the enum in its own header file and use it where it is required.
// my_enum.h
#pragma once
enum class L : int {
A, B, C, D
};
// TestClass.h
#pragma once
// Can forward declare L so long as we define the functions in the same cpp
// If original enum is in a namespace it needs to be forward declared in the same namespace
enum class L;
struct TestClass {
void foo(L n);
};
// TestClass.cpp
#include "TestClass.h"
#include "my_enum.h"
void TestClass::foo(L n)
{
// do stuff with n
}
// main.cpp
#include "TestClass.h"
#include "my_enum.h"
int main(){
TestClass main;
main.foo(L::D);
return 0;
}
How to solve this (in exact place, not move enum to a scope else) ?
I'm conscious that I've answered the question in a way you did not want, but I do not see why you wouldn't want to put the enum in its own file. Avoiding this will lead to problems at some point. The consequence of JeJo's solution is that you could pass any old integer in to foo() - it is essentially decoupled from the enum. If the integer value is supposed to originate from the enum L: 1) it isn't obvious from the function signature and 2) it is prone to misuse i.e. someone passing in a value they shouldn't.
If putting the enum in its own header file is an unacceptable solution, I'd be interested to know why.

Manipulating vectors inside class methods

I just started learning about vectors, and they seem really handy, if talking about lists from a file. But I'm having a problem while trying to return a new vector from a class method and put it to another method of the same class.
i.e.
#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;
class A
{
public:
string name;
string age;
};
class Test
{
string name;
string age;
public:
void get(vector<A> students)
{
vector<A> specificStudents;
//rewrite a couple of students from vector<A>students
//to vector<A> specificStudents
};
void set(vector<A> specificStudents)
{
//I need to get vector<A> specificStudents here
};
};
int main()
{
vector<A> students;
A stud;
ifstream file("file.txt");
for (int i = 0; i < file.eof(); i++)
{
getline(file, stud.name);
getline(file, stud.age);
students.push_back(stud);
};
Test test;
test.get(students);
return 0;
}
Can I return it as a function argument?
It is not entirely clear, but do you want to save a copy of students inside test?:
class Test
{
vector<A> specificStudents;
public:
const vector<A>& get() const
{
return specificStudents;
}
void set(const vector<A>& students)
{
specificStudents = students;
// maybe modify `specificStudents` here in some way or assign it differently
}
};
int main()
{
vector<A> students;
A stud;
ifstream file("file.txt");
while (getline(file, stud.name) && getline(file, stud.age))
{
students.push_back(stud);
}
Test test;
test.set(students);
//... Do something with test
return 0;
}
If you don't know yet what & and const mean in this, you can just remove them (until you learn about them).
You seem to have gotten get and set mixed up. By usual convention, get gets something stored in the class object to the caller and set sets something in the class object (with a value provided by the caller).
I also fixed your input loop. I don't know what you thought file.eof() does, but comparing to i does not do anything useful.
Also be aware of where ; belongs and where it doesn't. It belongs after single statements and class definitions, but not after } of function definitions or other statement blocks, such as the one of while.
YES, you can return vector from a function.
To do this you can write a function like this one:
std::vector<A> get(vector<A> students)
and the inside it return the vector. An example can be:
vector<A> get(vector<A> students)
{
vector<A> specificStudents;
//rewrite a couple of students from vector<A>students
//to vector<A> specificStudents
return specificStudents;
};

Enum in a class with strings

I'm trying to implement a class (C++) with an enum (with the permitted parameters). I got a working solution, but if I try to extend the functionality I get stuck.
Header data_location.hpp
class DataLocation
{
private:
public:
enum Params { model, period };
std::string getParamString(Params p);
};
Program data_location.cpp
string DataLocation::getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
The array ParamsStrings should be generally available in the class, because I need a second method (with inverse function) returning the enum value given a string.
If I try to define the array in the header I get the error:
in-class initialization of static data member ‘const char* DataLocation::ParamsStrings []’ of incomplete type
Why is the type incomplete? The compiler is for sure able to counts the strings in the array, isn't it?
In case there is no way to get my code working, is there an other way? With 1) no XML; 2) no double definition of the strings; 3) not outside the class; 4) no in code programmed mapping.
In class (header) use keyword static and initialize it outside (.cpp) without the static keyword:
class DataLocation {
public:
enum Params { model, period };
string getParamString(Params p);
static const char* ParamsStrings[];
// ^^^^^^
};
const char* DataLocation::ParamsStrings[] = {"MODEL", "BLLBLA"};
//^^^^^^^^^^^^^^^^^^^^^^^^
The code you have posted is perfectly fine.
Here's the proof:
#include <iostream>
#include <string>
struct DataLocation
{
enum Params { model, period };
std::string getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
};
int main()
{
auto a = DataLocation();
std::cout << a.getParamString(DataLocation::model) << std::endl;
return 0;
}
The error message you are getting is not to do with definition of a static data member in an inline function - that's allowed.
There's something else you're not showing us.
The main issue in my question (the second part) was that if I split the class in .hpp and .cpp the definition of the array (I mixed *char and string) has also to be split:
// data_location.hpp
class DataLocation {
static const char * ParamsStrings[];
}
// data_location.cpp
const char * ParamsStrings[] = {"MODEL", "PERIOD"};
At the end I introduced a consistency check to be sure that the number of values in enum growths as the number of strings. Because the array in C++ is somehow limited I had to go for a std::vector (to get the size).
Code for data_location.hpp
#ifndef DATA_LOCATION_HPP_
#define DATA_LOCATION_HPP_
#include <string>
#include "utils/dictionary.hpp"
extern const char* ENV_DATA_ROOT;
struct EDataLocationInconsistency : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct EDataLocationNotValidParam : std::runtime_error
{
using std::runtime_error::runtime_error;
};
class DataLocation
{
private:
std::string mRootLocation;
static const std::vector<std::string> msParamsStrings;
static bool msConsistenceCheckDone;
public:
DataLocation();
std::string getRootLocation();
std::string getLocation(Dictionary params);
enum Params { model, period, LAST_PARAM};
std::string Param2String(Params p);
Params String2Param(std::string p);
};
#endif
Code for data_location.cpp
#include "data_location.hpp"
#include <string>
#include <cstdlib>
using namespace std;
const char* ENV_DATA_ROOT = "DATA_ROOT";
bool DataLocation::msConsistenceCheckDone = false;
DataLocation::DataLocation() {
mRootLocation = std::getenv(ENV_DATA_ROOT);
if (not msConsistenceCheckDone) {
msConsistenceCheckDone = true;
if (LAST_PARAM+1 != msParamsStrings.size()) {
throw(EDataLocationInconsistency("DataLocation: Check Params and msParamsStrings"));
}
}
}
string DataLocation::getRootLocation() {
return mRootLocation;
}
string DataLocation::getLocation(Dictionary params) {
// to do
return "";
}
const vector<string> DataLocation::msParamsStrings = { "MODEL", "PERIOD", ""};
string DataLocation::Param2String(Params p) {
if (p>=msParamsStrings.size()) {
throw(EDataLocationNotValidParam("Parameter not found"));
}
return msParamsStrings[p];
}
DataLocation::Params DataLocation::String2Param(string p) {
for (int i = 0; i < msParamsStrings.size(); i++) {
if (p == msParamsStrings[i])
return (Params)i;
}
throw(EDataLocationNotValidParam("Parameter not found"));
}
And also a unit test:
#include <boost/test/unit_test.hpp>
#include "data_location.hpp"
#include <string>
using namespace std;
BOOST_AUTO_TEST_SUITE( data_location )
BOOST_AUTO_TEST_CASE(data_location_1) {
DataLocation dl;
auto s = dl.getRootLocation();
BOOST_CHECK_EQUAL(s, "/home/tc/data/forex" );
BOOST_CHECK_EQUAL(dl.Param2String(DataLocation::period),"PERIOD");
BOOST_CHECK_EQUAL(dl.String2Param("PERIOD"),DataLocation::period);
BOOST_CHECK_THROW(dl.String2Param("SOMETHING"), EDataLocationNotValidParam);
BOOST_CHECK_THROW(dl.Param2String((DataLocation::Params)100), EDataLocationNotValidParam);
}
BOOST_AUTO_TEST_SUITE_END()
C++ is very picky about what it will let you initialize inside of a class definition; there are some particularly non-intuitive rules surrounding static members. It all has to do with the ODR, and why all the rules are the way they are is not especially important.
To cut to the chase, making your array a static constexpr const member should shut the compiler up. With the C++11 standard, the restrictions were relaxed a bit, and one of the new stipulations was that static constexpr members can be initialized inline. This is perfect for your application, since the strings in your array are compile-time constants.
The recent g++ compiler which support C++0x or later compiles thus code. Pure C compile compiles, too. Because strings in initialization like {"MODEL", "PERIOD"}; implemented as const char * pointer to the char array.

How can I initialize char arrays in a constructor?

I'm having trouble declaring and initializing a char array. It always displays random characters. I created a smaller bit of code to show what I'm trying in my larger program:
class test
{
private:
char name[40];
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
std::cin>>x;
}
};
test::test()
{
char name [] = "Standard";
}
int main()
{ test *test1 = new test;
test1->display();
}
And sorry if my formatting is bad, I can barely figure out this website let alone how to fix my code :(
If there are no particular reasons to not use std::string, do use std::string.
But if you really need to initialize that character array member, then:
#include <assert.h>
#include <iostream>
#include <string.h>
using namespace std;
class test
{
private:
char name[40];
int x;
public:
test();
void display() const
{
std::cout<<name<<std::endl;
}
};
test::test()
{
static char const nameData[] = "Standard";
assert( strlen( nameData ) < sizeof( name ) );
strcpy( name, nameData );
}
int main()
{
test().display();
}
Your constructor is not setting the member variable name, it's declaring a local variable. Once the local variable goes out of scope at the end of the constructor, it disappears. Meanwhile the member variable still isn't initialized and is filled with random garbage.
If you're going to use old-fashioned character arrays you'll also need to use an old-fashioned function like strcpy to copy into the member variable. If all you want to do is set it to an empty string you can initialize it with name[0] = 0.
Since you are using C++, I suggest using strings instead of char arrays. Otherwise you'd need to employ strcpy (or friends).
Also, you forgot to delete the test1 instance.
#include <iostream>
#include <string>
class test
{
private:
std::string name;
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
}
};
test::test()
{
name = "Standard";
}
int main()
{
test test1;
test1.display();
std::cin>>x;
}
Considering you tagged the question as C++, you should use std::string:
#include <string>
class test
{
private:
std::string name;
int x;
public:
test();
void display()
{
std::cout<<name<<std::endl;
std::cin>>x;
}
};
test::test() : name("Standard")
{
}
c++11 actually provides two ways of doing this. You can default the member on it's declaration line or you can use the constructor initialization list.
Example of declaration line initialization:
class test1 {
char name[40] = "Standard";
public:
void display() { cout << name << endl; }
};
Example of constructor initialization:
class test2 {
char name[40];
public:
test2() : name("Standard") {};
void display() { cout << name << endl; }
};
You can see a live example of both of these here: http://ideone.com/zC8We9
My personal preference is to use the declaration line initialization because:
Where no other variables must be constructed this allows the generated default constructor to be used
Where multiple constructors are required this allows the variable to be initialized in only one place rather than in all the constructor initialization lists
Having said all this, using a char[] may be considered damaging as the generated default assignment operator, and copy/move constructors won't work. This can be solved by:
Making the member const
Using a char* (this won't work if the member will hold anything but a literal string)
In the general case std::string should be preferred

C++ class member function callback

I have the following problem. I have a function from an external library (which cannot be modified) like this:
void externalFunction(int n, void udf(double*) );
I would like to pass as the udf function above a function member of an existing class. Please look at the following code:
// External function (tipically from an external library)
void externalFunction(int n, void udf(double*) )
{
// do something
}
// User Defined Function (UDF)
void myUDF(double* a)
{
// do something
}
// Class containing the User Defined Function (UDF)
class myClass
{
public:
void classUDF(double* a)
{
// do something...
};
};
int main()
{
int n=1;
// The UDF to be supplied is myUDF
externalFunction(n, myUDF);
// The UDF is the classUDF member function of a myClass object
myClass myClassObj;
externalFunction(n, myClassObj.classUDF); // ERROR!!
}
I cannot declare the classUDF member function as a static function, so the last line of the code above results in a compilation error!
This is impossible to do - in c++, you must use either a free function, or a static member function, or (in c++11) a lambda without capture to get a function pointer.
GCC allows you to create nested function which could do what you want, but only in C. It uses so-called trampolines to do that (basically small pieces of dynamically generated code). It would be possible to use this feature, but only if you split some of the code calling externalFunction to a separate C module.
Another possibility would be generating code at runtime eg. using libjit.
So if you're fine with non-reenrant function, create a global/static variable which will point to this and use it in your static function.
class myClass
{
public:
static myClass* callback_this;
static void classUDF(double* a)
{
callback_this.realUDF(a);
};
};
Its really horrible code, but I'm afraid you're out of luck with such a bad design as your externalFunction.
You can use Boost bind or TR1 bind (on recent compilers);;
externalFunction(n, boost::bind(&myClass::classUDF, boost::ref(myClassObj)));
Unfortunately, I lived in a pipe dream for the last 10 minutes. The only way forward is to call the target using some kind of a static wrapper function. The other answers have various neat (compiler-specific) tidbits on that, but here's the main trick:
void externalFunction(int n, void (*udf)(double*) )
{ double x; udf(&x); }
myClass myClassObj;
void wrapper(double* d) { myClassObj.classUDF(d); }
int main()
{
externalFunction(1, &wrapper);
}
std::function<>
Store a bound function in a variable like this:
std::function<void(double*)> stored = std::bind(&myClass::classUDF, boost::ref(myClassObj))
(assuming C++0x support in compiler now. I'm sure Boost has a boost::function<> somewhere)
Vanilla C++ pointers-to-member-function
Without magic like that, you'd need pointer-to-memberfunction syntax:
See also live on http://ideone.com/Ld7It
Edit to clarify to the commenters, obviously this only works iff you have control over the definition of externalFunction. This is in direct response to the /broken/ snippet int the OP.
struct myClass
{
void classUDF(double* a) { };
};
void externalFunction(int n, void (myClass::*udf)(double*) )
{
myClass myClassObj;
double x;
(myClassObj.*udf)(&x);
}
int main()
{
externalFunction(1, &myClass::classUDF);
}
C++98 idiomatic solution
// mem_fun_ref example
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <string>
int main ()
{
std::vector<std::string> numbers;
// populate vector:
numbers.push_back("one");
numbers.push_back("two");
numbers.push_back("three");
numbers.push_back("four");
numbers.push_back("five");
std::vector <int> lengths (numbers.size());
std::transform (numbers.begin(), numbers.end(), lengths.begin(),
std::mem_fun_ref(&std::string::length));
for (int i=0; i<5; i++) {
std::cout << numbers[i] << " has " << lengths[i] << " letters.\n";
}
return 0;
}
Here is how I do this, when MyClass is a singleton:
void externalFunction(int n, void udf(double) );
class MyClass
{
public:
static MyClass* m_this;
MyClass(){ m_this = this; }
static void mycallback(double* x){ m_this->myrealcallback(x); }
void myrealcallback(double* x);
}
int main()
{
MyClass myClass;
externalFunction(0, MyClass::mycallback);
}