Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #14694 > unrolled thread

Declaring a static const member of a class.

Started byLuca Cerone <luca.cerone@gmail.com>
First post2012-03-02 08:26 -0800
Last post2012-03-04 01:40 -0500
Articles 9 — 6 participants

Back to article view | Back to comp.lang.c++


Contents

  Declaring a static const member of a class. Luca Cerone <luca.cerone@gmail.com> - 2012-03-02 08:26 -0800
    Re: Declaring a static const member of a class. Ed Anson <EdAnson@comcast.net> - 2012-03-02 18:49 -0500
      Re: Declaring a static const member of a class. Leigh Johnston <leigh@i42.co.uk> - 2012-03-03 11:02 +0000
      Re: Declaring a static const member of a class. Luca Cerone <luca.cerone@gmail.com> - 2012-03-03 04:35 -0800
        Re: Declaring a static const member of a class. Paavo Helde <myfirstname@osa.pri.ee> - 2012-03-03 07:21 -0600
        Re: Declaring a static const member of a class. Ed Anson <EdAnson@comcast.net> - 2012-03-03 13:04 -0500
    Re: Declaring a static const member of a class. Saeed Amrollahi <amrollahi.saeed@gmail.com> - 2012-03-03 03:29 -0800
    Re: Declaring a static const member of a class. Luca Cerone <luca.cerone@gmail.com> - 2012-03-03 10:33 -0800
      Re: Declaring a static const member of a class. Pavel <pauldontspamtolk@removeyourself.dontspam.yahoo> - 2012-03-04 01:40 -0500

#14694 — Declaring a static const member of a class.

FromLuca Cerone <luca.cerone@gmail.com>
Date2012-03-02 08:26 -0800
SubjectDeclaring a static const member of a class.
Message-ID<2939750.182.1330705614328.JavaMail.geo-discussion-forums@vbva11>
Dear all,

I'm having a few difficulties in declaring a class with a static constant member.
This member is a vector of double that has to be created once during
the execution and shared among all the objects.
After being created it can't be modified during the whole execution of my program.

I write a toy example to show you what I'd like to do (it doesn't work,
but I can't figure out a way to code it well, that's why I'm posting here).

#include<iostream>
#include<vector>

class QuadFun{
  public:
    QuadFun(double a, double b) ; // a and b will be used to initialize
    // the private vector y to evaluate the values (x-a)*(x-b)
    // x has to be a vector that is shared among all the object of the class.
  private:
    static const std::vector<double> x; // this will be a vector of uniformly
           //spaced numbers from 0 to 1. The number of points is determined
           //by reading a configuration file. in this example I set the  
           //number manually in the main function.
    std::vector<double> y;
}

int main() {
  int numPoints=50; // this value is actually read from a configuration file
  // here is the problem. I don't want the number of points to be a member
  // of the class.
  QuadFun f1=QuadFun(0,1);
  QuadFun f2=QuadFun(0.5,0.75);
  
  // how can I make the vector x mad of numpoints created when I first create
  // an object of class QuadFun?
  // how can I make it "dynamic" so that if I change the value of numPoints
  // the x vector will be created accordingly? (in an other execution).
  return 0 ;
}

Hope I could explain well what I'd like to achieve.
I know this code is WRONG, but I can't understand how to write it
in a good way.

Can you help me?
Thanks a lot in advance,
Cheers, Luca




[toc] | [next] | [standalone]


#14699

FromEd Anson <EdAnson@comcast.net>
Date2012-03-02 18:49 -0500
Message-ID<WM2dnWIIfKoewczSnZ2dnUVZ_o-dnZ2d@giganews.com>
In reply to#14694
On 3/2/12 11:26 AM, Luca Cerone wrote:
> Dear all,
>
> I'm having a few difficulties in declaring a class with a static constant member.
> This member is a vector of double that has to be created once during
> the execution and shared among all the objects.
> After being created it can't be modified during the whole execution of my program.
>
> I write a toy example to show you what I'd like to do (it doesn't work,
> but I can't figure out a way to code it well, that's why I'm posting here).
>
> #include<iostream>
> #include<vector>
>
> class QuadFun{
>    public:
>      QuadFun(double a, double b) ; // a and b will be used to initialize
>      // the private vector y to evaluate the values (x-a)*(x-b)
>      // x has to be a vector that is shared among all the object of the class.
>    private:
>      static const std::vector<double>  x; // this will be a vector of uniformly
>             //spaced numbers from 0 to 1. The number of points is determined
>             //by reading a configuration file. in this example I set the
>             //number manually in the main function.
>      std::vector<double>  y;
> }
>
> int main() {
>    int numPoints=50; // this value is actually read from a configuration file
>    // here is the problem. I don't want the number of points to be a member
>    // of the class.
>    QuadFun f1=QuadFun(0,1);
>    QuadFun f2=QuadFun(0.5,0.75);
>
>    // how can I make the vector x mad of numpoints created when I first create
>    // an object of class QuadFun?
>    // how can I make it "dynamic" so that if I change the value of numPoints
>    // the x vector will be created accordingly? (in an other execution).
>    return 0 ;
> }
>
> Hope I could explain well what I'd like to achieve.
> I know this code is WRONG, but I can't understand how to write it
> in a good way.
>
> Can you help me?
> Thanks a lot in advance,
> Cheers, Luca


Luca,

You have three problems here:
1. The C++ concept of const does not strictly allow for run-time 
initialization such as you desire; and
2. Initialization in the constructor (which might be different for each 
instance) is inconsistent with the static definition (which is shared by 
all instances).
3. A static const requires a definition with an initial value.

The third problem is essentially a syntax error. The usual solution for 
the second problem would be to add a static member function to 
initialize the vector. And here is a reasonably good solution to the 
first problem:

In the function you use to initialize the vector, use const_cast to 
obtain a non-const pointer to the vector. You can then initialize it as 
you require. If it is inconvenient to guarantee that the initialization 
function is called only once, you might instead declare the static 
member as a pointer to vector, declared with value NULL. If the 
initialization function sees NULL, it instantiates the vector, 
initializes it as desired, and then sets the pointer (using const_cast).

This is a fairly standard work-around when it is necessary to bend the 
concept of const to something similar to (but different from) the C++ 
concept.

/Ed

[toc] | [prev] | [next] | [standalone]


#14702

FromLeigh Johnston <leigh@i42.co.uk>
Date2012-03-03 11:02 +0000
Message-ID<f7CdnTu4qpH-Z8zSnZ2dnUVZ8nqdnZ2d@giganews.com>
In reply to#14699
On 02/03/2012 23:49, Ed Anson wrote:
> On 3/2/12 11:26 AM, Luca Cerone wrote:
>> Dear all,
>>
>> I'm having a few difficulties in declaring a class with a static
>> constant member.
>> This member is a vector of double that has to be created once during
>> the execution and shared among all the objects.
>> After being created it can't be modified during the whole execution of
>> my program.
>>
>> I write a toy example to show you what I'd like to do (it doesn't work,
>> but I can't figure out a way to code it well, that's why I'm posting
>> here).
>>
>> #include<iostream>
>> #include<vector>
>>
>> class QuadFun{
>> public:
>> QuadFun(double a, double b) ; // a and b will be used to initialize
>> // the private vector y to evaluate the values (x-a)*(x-b)
>> // x has to be a vector that is shared among all the object of the class.
>> private:
>> static const std::vector<double> x; // this will be a vector of uniformly
>> //spaced numbers from 0 to 1. The number of points is determined
>> //by reading a configuration file. in this example I set the
>> //number manually in the main function.
>> std::vector<double> y;
>> }
>>
>> int main() {
>> int numPoints=50; // this value is actually read from a configuration
>> file
>> // here is the problem. I don't want the number of points to be a member
>> // of the class.
>> QuadFun f1=QuadFun(0,1);
>> QuadFun f2=QuadFun(0.5,0.75);
>>
>> // how can I make the vector x mad of numpoints created when I first
>> create
>> // an object of class QuadFun?
>> // how can I make it "dynamic" so that if I change the value of numPoints
>> // the x vector will be created accordingly? (in an other execution).
>> return 0 ;
>> }
>>
>> Hope I could explain well what I'd like to achieve.
>> I know this code is WRONG, but I can't understand how to write it
>> in a good way.
>>
>> Can you help me?
>> Thanks a lot in advance,
>> Cheers, Luca
>
>
> Luca,
>
> You have three problems here:
> 1. The C++ concept of const does not strictly allow for run-time
> initialization such as you desire; and
> 2. Initialization in the constructor (which might be different for each
> instance) is inconsistent with the static definition (which is shared by
> all instances).
> 3. A static const requires a definition with an initial value.
>
> The third problem is essentially a syntax error. The usual solution for
> the second problem would be to add a static member function to
> initialize the vector. And here is a reasonably good solution to the
> first problem:
>
> In the function you use to initialize the vector, use const_cast to
> obtain a non-const pointer to the vector. You can then initialize it as
> you require. If it is inconvenient to guarantee that the initialization
> function is called only once, you might instead declare the static
> member as a pointer to vector, declared with value NULL. If the
> initialization function sees NULL, it instantiates the vector,
> initializes it as desired, and then sets the pointer (using const_cast).
>
> This is a fairly standard work-around when it is necessary to bend the
> concept of const to something similar to (but different from) the C++
> concept.

It is undefined behaviour to modify a const object via a non-const 
reference obtained via const_cast.

The correct solution is:

std::vector<double> shared_initialization_data()
{
	...
}

const std::vector<double> QuadFun::x = shared_initialization_data();

HTH.

/Leigh

[toc] | [prev] | [next] | [standalone]


#14705

FromLuca Cerone <luca.cerone@gmail.com>
Date2012-03-03 04:35 -0800
Message-ID<22573415.56.1330778113342.JavaMail.geo-discussion-forums@vbas10>
In reply to#14699
Hi Ed, thanks a lot for your reply!
>On Friday, March 2, 2012 11:49:26 PM UTC, Ed Anson wrote:
> You have three problems here:
> 1. The C++ concept of const does not strictly allow for run-time 
> initialization such as you desire; and
> 2. Initialization in the constructor (which might be different for each 
> instance) is inconsistent with the static definition (which is shared by 
> all instances).
> 3. A static const requires a definition with an initial value.
> 

Ok probably I got everything wrong.
I thought that you used const to avoid overwriting a value that has already been defined; and I thought that static (for class members) is used to share 
the same location of memory among all the objects.

So the idea of declaring something as static const correspond to "initialize
the member once, share it among all the objects and forbid modifications".

As this is wrong, what is "static const" actually used for?

> The third problem is essentially a syntax error. The usual solution for 
> the second problem would be to add a static member function to 
> initialize the vector. And here is a reasonably good solution to the 
> first problem:
> 
> In the function you use to initialize the vector, use const_cast to 
> obtain a non-const pointer to the vector.

I'm sorry I'm not aware of the const_cast type... what is it?

> You can then initialize it as 
> you require. If it is inconvenient to guarantee that the initialization 
> function is called only once, you might instead declare the static 
> member as a pointer to vector, declared with value NULL. If the 
> initialization function sees NULL, it instantiates the vector, 
> initializes it as desired, and then sets the pointer (using const_cast).
> 

ok I think I got it..
so in my class I need a static pointer to a vector x, initially set to null that is assigned by the constructor (if it is not null).
But how can I avoid writing on x again?


> This is a fairly standard work-around when it is necessary to bend the 
> concept of const to something similar to (but different from) the C++ 
> concept.
> 
> /Ed

I actually don't understand something though.
It seems pretty reasonable to me that a class object my depend on certain
parameters input by the user somehow (keyboard, reading a file etc. etc.).

Isn't there a way to "parameterize" a class, so that its members will depend
on certain parameters?

Thanks again for your answer.
I'm sorry if I ask silly question, I'm a 3weeks "experienced" c++ programmer,
and after 10 years of Matlab programming I feel like I've never programmed before :)

Cheers, 
Luca

[toc] | [prev] | [next] | [standalone]


#14706

FromPaavo Helde <myfirstname@osa.pri.ee>
Date2012-03-03 07:21 -0600
Message-ID<XnsA00B9C3FE787Bmyfirstnameosapriee@216.196.109.131>
In reply to#14705
Luca Cerone <luca.cerone@gmail.com> wrote in
news:22573415.56.1330778113342.JavaMail.geo-discussion-forums@vbas10: 

> Hi Ed, thanks a lot for your reply!
>>On Friday, March 2, 2012 11:49:26 PM UTC, Ed Anson wrote:
>> You have three problems here:
>> 1. The C++ concept of const does not strictly allow for run-time 
>> initialization such as you desire; and
>> 2. Initialization in the constructor (which might be different for
>> each instance) is inconsistent with the static definition (which is
>> shared by all instances).
>> 3. A static const requires a definition with an initial value.
>> 
> 
> Ok probably I got everything wrong.
> I thought that you used const to avoid overwriting a value that has
> already been defined; and I thought that static (for class members) is
> used to share the same location of memory among all the objects.

In principle you are right. However, 'static const' data members of 
classes are normally initialized before main() is entered. This means 
that you cannot pass e.g. init file name as the command-line argument as 
it will be processed only in main(). 

If this is not a concern, then you can easily have a static const 
std::vector:

#include<iostream>
#include<vector>

class QuadFun{
  public:
    QuadFun(double a, double b) ; // a and b will be used to initialize
    // the private vector y to evaluate the values (x-a)*(x-b)
    // x has to be a vector that is shared among all the object of the 
class.
  private:
    static const std::vector<double> x; // this will be a vector of 
uniformly
           //spaced numbers from 0 to 1. The number of points is 
determined
           //by reading a configuration file. in this example I set the  
           //number manually in the main function.
    std::vector<double> y;
};

std::vector<double> InitializeVector() {
	const int numPoints=50;
	std::vector<double> x(numPoints);
	for (int i=0; i<numPoints; ++i) {
		x[i] = double(i)/numPoints;
	}
	return x;
}

// static member requires separate definition/initialization 
// in a .cpp file:
const std::vector<double> QuadFun::x = InitializeVector();

> I'm sorry I'm not aware of the const_cast type... what is it?

If you do not know what is const_cast you need to reread your C++ book.

> 
> I actually don't understand something though.
> It seems pretty reasonable to me that a class object my depend on
> certain parameters input by the user somehow (keyboard, reading a file
> etc. etc.). 
> 
> Isn't there a way to "parameterize" a class, so that its members will
> depend on certain parameters?

It becomes difficult with a 'const static' data member as the 
initialization may happen too early. A 'const static' local variable 
inside a function would be more flexible in this regard.

> 
> Thanks again for your answer.
> I'm sorry if I ask silly question, I'm a 3weeks "experienced" c++
> programmer, and after 10 years of Matlab programming I feel like I've
> never programmed before :) 

You are welcome. Just do not expect to be proficient in C++ in another 3 
weeks, it will take years.

hth
Paavo

[toc] | [prev] | [next] | [standalone]


#14723

FromEd Anson <EdAnson@comcast.net>
Date2012-03-03 13:04 -0500
Message-ID<fYudnbPyBozbwM_SnZ2dnUVZ_sadnZ2d@giganews.com>
In reply to#14705
On 3/3/12 7:35 AM, Luca Cerone wrote:
> Hi Ed, thanks a lot for your reply!
>> On Friday, March 2, 2012 11:49:26 PM UTC, Ed Anson wrote:
>> You have three problems here:
>> 1. The C++ concept of const does not strictly allow for run-time
>> initialization such as you desire; and
>> 2. Initialization in the constructor (which might be different for each
>> instance) is inconsistent with the static definition (which is shared by
>> all instances).
>> 3. A static const requires a definition with an initial value.
>>
>
> Ok probably I got everything wrong.
> I thought that you used const to avoid overwriting a value that has already been defined; and I thought that static (for class members) is used to share
> the same location of memory among all the objects.

That is correct. A const value cannot be changed after it is 
initialized. However, it is initialized at its point of definition. 
Consequently, a static const is usually initialized before the program 
starts running.

I should have elaborated on problem 3: A static const requires a 
definition with an initial value, which must necessarily be evaluated 
before the program starts running. Using a file (as you want) to 
initialize it is not an option. Such behavior is decidedly not const.

>
> So the idea of declaring something as static const correspond to "initialize
> the member once, share it among all the objects and forbid modifications".
>
> As this is wrong, what is "static const" actually used for?

Static const is used when the value is shared by all instances (objects) 
of a class, and has a value defined before the program starts running.

>
>> The third problem is essentially a syntax error. The usual solution for
>> the second problem would be to add a static member function to
>> initialize the vector. And here is a reasonably good solution to the
>> first problem:
>>
>> In the function you use to initialize the vector, use const_cast to
>> obtain a non-const pointer to the vector.
>
> I'm sorry I'm not aware of the const_cast type... what is it?

The const_cast operator is specifically provided for casting away the 
const of a value. As another person has correctly mentioned, it is not 
always safe to use it on a const object; it is generally used in other 
contexts where the object has acquired const status. But it still works 
in most implementations. Its syntax and use are described in any good 
book on C++.

But (after a bit more reflection) I think you don't really need const in 
your application. Making it private should be enough, and more 
accurately reflects your intent to set its value after execution begins. 
Because it's private, your class can determine when (and how many times) 
its value gets set. A static method designed for the purpose is a common 
way to handle that.

>
>> You can then initialize it as
>> you require. If it is inconvenient to guarantee that the initialization
>> function is called only once, you might instead declare the static
>> member as a pointer to vector, declared with value NULL. If the
>> initialization function sees NULL, it instantiates the vector,
>> initializes it as desired, and then sets the pointer (using const_cast).
>>
>
> ok I think I got it..
> so in my class I need a static pointer to a vector x, initially set to null that is assigned by the constructor (if it is not null).
> But how can I avoid writing on x again?

If x is private to your class, it controls that. Any use outside of the 
class would require an accessor, such as:

private: static vector<int> x;
public:  static const vector<int>& GetVector() { return x; }

> I actually don't understand something though.
> It seems pretty reasonable to me that a class object my depend on certain
> parameters input by the user somehow (keyboard, reading a file etc. etc.).
>
> Isn't there a way to "parameterize" a class, so that its members will depend
> on certain parameters?

You can use a constrtuctor to parameterize instances of a class 
(objects). But you want all objects of the class to share the same data. 
That calls for an initialization function to set the shared data.

>
> Thanks again for your answer.
> I'm sorry if I ask silly question, I'm a 3weeks "experienced" c++ programmer,
> and after 10 years of Matlab programming I feel like I've never programmed before :)

Don't feel bad. I've been programming with C++ for 23 years and I'm 
still learning.

>
> Cheers,
> Luca

[toc] | [prev] | [next] | [standalone]


#14703

FromSaeed Amrollahi <amrollahi.saeed@gmail.com>
Date2012-03-03 03:29 -0800
Message-ID<45ee09ab-cdbe-472b-a980-9aa76bd23f83@eb6g2000vbb.googlegroups.com>
In reply to#14694
On Mar 2, 7:26 pm, Luca Cerone <luca.cer...@gmail.com> wrote:
> Dear all,
>
> I'm having a few difficulties in declaring a class with a static constant member.
> This member is a vector of double that has to be created once during
> the execution and shared among all the objects.
> After being created it can't be modified during the whole execution of my program.
>
> I write a toy example to show you what I'd like to do (it doesn't work,
> but I can't figure out a way to code it well, that's why I'm posting here).
>
> #include<iostream>
> #include<vector>
>
> class QuadFun{
>   public:
>     QuadFun(double a, double b) ; // a and b will be used to initialize
>     // the private vector y to evaluate the values (x-a)*(x-b)
>     // x has to be a vector that is shared among all the object of the class.
>   private:
>     static const std::vector<double> x; // this will be a vector of uniformly
>            //spaced numbers from 0 to 1. The number of points is determined
>            //by reading a configuration file. in this example I set the
>            //number manually in the main function.
>     std::vector<double> y;
>
> }
>
> int main() {
>   int numPoints=50; // this value is actually read from a configuration file
>   // here is the problem. I don't want the number of points to be a member
>   // of the class.
>   QuadFun f1=QuadFun(0,1);
>   QuadFun f2=QuadFun(0.5,0.75);
>
>   // how can I make the vector x mad of numpoints created when I first create
>   // an object of class QuadFun?
>   // how can I make it "dynamic" so that if I change the value of numPoints
>   // the x vector will be created accordingly? (in an other execution).
>   return 0 ;
>
> }
>
> Hope I could explain well what I'd like to achieve.
> I know this code is WRONG, but I can't understand how to write it
> in a good way.
>
> Can you help me?
> Thanks a lot in advance,
> Cheers, Luca

Hello
My pretty quick solution:
// quad_fun.h
#include<vector>

class QuadFun{
  public:
    QuadFunc(double a, double b);
    const std::vector<double> GetY() const { return y; }
    static bool filled; // to make sure, we filled x already
  private:
    static std::vector<double> x;
    static void FillX(); // static member function for filling X
    std::vector<double> y;
};

// quad_fun.cpp
#include "quad_fun.h"
using std::vector;
vector<double> QuadFun::x;
bool QuadFun::filled = false;
extern int numPoints;

QuadFun::QuadFun(double a, double b)
{
  FillX();
  y.clear();
  for (vector<double>::size_type i = 0; i < x.size(); ++i)
    y.push_back((x[i] - a) * (x[i] - b));
}

void QuadFun::FillX()
{
  if (!filled)
    for (int i = 0; i < numPoints; ++i)
      x.push_back(i % 3 + 0.0); // fill with 0 or 1, just an example
    filled = true;
}

// quad_fun_main.cpp
#include "quad_fun.h"
#include <iostream>
#include <algorithm>
#include <iterator>

int numPoints; // this value is actually read from a configuration
file
int main() {
  using namespace std;

  cout << "Number of points ";
  cin >> numPoints;
  QuadFun f1= QuadFun(0,1);
  vector<double> y = f1.GetY();
  copy(y.begin(), y.end(), ostream_iterator<double>(cout, "\t"));
  cout << '\n';
  QuadFun f2=QuadFun(0.5,0.75);
  y = f2.GetY();
  copy(y.begin(), y.end(), ostream_iterator<double>(cout, "\t"));
  return 0 ;
}

HTH,
  -- Saeed Amrollahi Boyouki

[toc] | [prev] | [next] | [standalone]


#14724

FromLuca Cerone <luca.cerone@gmail.com>
Date2012-03-03 10:33 -0800
Message-ID<18041019.646.1330799599487.JavaMail.geo-discussion-forums@vbux23>
In reply to#14694
Thanks a lot to all of you.
I've received many inputs and I hope I'll be able to make
things work soon.

Creating the a public accessor, and a private member to set the
value seems a good idea.

Thanks a lot for the explanations,
the examples and the different solutions proposed!

Cheers, Luca

[toc] | [prev] | [next] | [standalone]


#14736

FromPavel <pauldontspamtolk@removeyourself.dontspam.yahoo>
Date2012-03-04 01:40 -0500
Message-ID<4f530e4c$0$20354$c3e8da3$a8a65a91@news.astraweb.com>
In reply to#14724
Luca Cerone wrote:
> Thanks a lot to all of you.
> I've received many inputs and I hope I'll be able to make
> things work soon.
>
> Creating the a public accessor, and a private member to set the
> value seems a good idea.
>
> Thanks a lot for the explanations,
> the examples and the different solutions proposed!
>
> Cheers, Luca
>
Meyer's singleton may fit your description better (to create x when you first 
create QuadFun -- that is, not to initialize it at all if you do not create 
them). For example:


class QuadFun{
   public:
     QuadFun(double a, double b) ; // a and b will be used to initialize
     // the private vector y to evaluate the values (x-a)*(x-b)
     // x has to be a vector that is shared among all the object of the class.
   private:
     static const std::vector<double> &GetX() {
	static std::auto_ptr<const std::vector<double> >
		x(InitializeXFromConfigFile());
	return *x;
     }
     static std::vector<double> * InitializeXFromConfigFile(); // not shown
// this will be a vector of uniformly
            //spaced numbers from 0 to 1. The number of points is determined
            //by reading a configuration file. in this example I set the
            //number manually in the main function.
     std::vector<double> y;
}

QuadFun::QuadFun(double a, double b): y() {
	const std::vector<double> &x = GetX();
	unsigned n = x.size();
	y.reserve(n);	
	for (unsigned i = 0;  i < n;  ++i)
		y[i] = (x[i] - a) * (x[i] - b);
}

Disclaimers: I did not try to complile the above and Meyer's singletons "in 
pure" are not "thread-safe".

HTH
-Pavel

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web