LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   In-Class initialization of constant member (https://www.linuxquestions.org/questions/programming-9/in-class-initialization-of-constant-member-703309/)

unihiekka 02-09-2009 05:00 AM

In-Class initialization of constant member
 
I know it's not possible to define a non-integer static const in C++ inside the definition of a class for obvious reasons of possible multiple instances of the same object through multiple inclusion of the same libraries. However, I would like to know if there is a way to work around that problem, because I have template that uses the type (int, float, double, quad, ...) as an argument and depending on that the constants should be of the same type (that has to do with allowing multiple precision computations). So putting these constants in a separate file (or at least outside of the class) is not really an option, because then I'd have to assign a type, which I don't want to do. Any suggestions?

dwhitney67 02-09-2009 12:00 PM

Quote:

Originally Posted by unihiekka (Post 3436996)
I know it's not possible to define a non-integer static const in C++ inside the definition of a class for obvious reasons...

I don't quite understand this statement; the following is permissible in C++:
Code:

class Foo
{
  static const double VALUE = 10.3;
};

One can even do:
Code:

template <typename T>
class Foo
{
  static const T VALUE = 10.3;  // note that for integers, fractional portion of the value is dropped.
};

Now if typename T is something more complex, such as an std::string or a 'quad' (what is this??), then all bets are off.

Anyhow, maybe I missed the issue you are having trouble with.

Biddle 02-09-2009 06:43 PM

I had left this thread but seeing as there has not been a correction:
Quote:

I don't quite understand this statement; the following is permissible in C++:
The code you posted after this comment is not valid C++.

How about
Code:

template<typename T>
struct foo
{
        static const T value;
};

template<>const float foo<float>::value = 1.f;
template<>const double foo<double>::value = 1.0;
template<>const int foo<int>::value = 5;
template<>const std::string foo<std::string>::value = "some value";

Or maybe setting the const in the constructor like
Code:

template<typename T>
struct foo
{
        foo();
        const T value;
};

template<>foo<float>::foo():value(1.f){}
template<>foo<double>::foo():value(1.0){}
...


johnsfine 02-09-2009 10:10 PM

To get around that issue, the project I work on has frequently put function statics inside inline member functions.

Obviously, the syntax to access the "static" is different than if it were directly a class static, but the semantics are the same. Typically, the member function in which you wrap the static does nothing other than return a reference to that static.

We have discovered several bugs in the Intel compiler (version 7 through 10) in compiling that construct and in several cases we needed to do something else because of compiler bugs when the code was correct. But those bugs were in fairly complicated examples and I expect you're using gcc, not intel as a compiler. I don't know of similar bugs in gcc.

Code:

template<typename T>
struct foo
{
    T& act_like_a_class_static_value()
    {
        static T st;
        return st;
    }
};

You can add const and initialization as appropriate. (I can't tell from your description where the initial value should come from.)

Technically it is more correct for the function to be class static as well, and when it matters we do that.

ta0kira 02-09-2009 11:56 PM

Quote:

Originally Posted by Biddle (Post 3437765)
The code you posted after this comment is not valid C++.

Yes it is, and in fact it's critical for using partial-specialization as a sort of pre-processor:
Code:

#include <iostream>


template <class>
struct pointer_check
{
    static const bool pointer = false;
};


template <class Type>
struct pointer_check <Type*>
{
    static const bool pointer = true;
};


template <bool>
struct do_something {};


template <>
struct do_something <true>
{
    static inline void something()
    { std::cout << "is a pointer\n"; }
};


template <>
struct do_something <false>
{
    static inline void something()
    { std::cout << "is not a pointer\n"; }
};


template <class Type>
void show_isa_pointer()
{ do_something <pointer_check <Type> ::pointer> ::something(); }


int main()
{
    show_isa_pointer <int> ();
    show_isa_pointer <int*> ();
}

Run it through Comeau and through g++.
ta0kira

PS There are less trivial reasons to use this, but my example is just to show that it works.

Biddle 02-10-2009 04:02 AM

Quote:

Originally Posted by ta0kira (Post 3437955)
Yes it is, and in fact it's critical for using partial-specialization as a sort of pre-processor:Run it through Comeau and through g++.
ta0kira

I do not need to run dwhitney67's code through g++ or an online checker I know it is not valid, why do you not try it yourself and see? The type has to be a constant integral or enumeration type.
I would also add that I do not think your code is valid either, it should have an out of class definition as well.

Quote:

9.4.2.2
The declaration of a static data member in its class definition is not a definition and may be of an
incomplete type other than cv-qualified void. The definition for a static data member shall appear in a
namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name
of the static data member shall be qualified by its class name using the :: operator. The initializer
expression in the definition of a static data member is in the scope of its class (3.3.6).
9.4.2.4
If a static data member is of const integral or const enumeration type, its declaration in the class
definition can specify a constant-initializer which shall be an integral constant expression (5.19). In that
case, the member can appear in integral constant expressions. The member shall still be defined in a namespace
scope if it is used in the program and the namespace scope definition shall not contain an initializer.


All times are GMT -5. The time now is 01:39 PM.