[Dune] Warnings about FieldVector::size

Martin Nolte nolte at mathematik.uni-freiburg.de
Tue Aug 16 19:26:36 CEST 2011


Yes, I did mean the situation where the member is not defined. As far as I see
it, defining it is not possible because
(a) it is a tempalte and needs instantiation
(b) it cannot be instantiated within the header, because this yields multiple
definitions in multiple object files.

As to taking the address, things are different. You're right, the compiler
cannot take the address of an enum and, hence, won't do so. With a static
member, the compiler may take the address, though. Consider the following
(valid) situation:

void foo ( const size_t &s );

void bar ()
{
  foo( FieldVector< double, 2 >::size );
}

Let's neglect inlining for a second (we can enforce by putting the two parts
into separate object files)
With a static member, the compiler will actually pass the reference, here. For
an enum, the required copy will be made.

Test this for yourself!

Best,

Martin


On 08/16/2011 06:38 PM, Jö Fahlke wrote:
> Am Tue, 16. Aug 2011, 16:43:04 +0200 schrieb Martin Nolte:
>> Using a static const member variable can lead to linker errors, if a reference
>> to this constant is passed by the compiler.
>> I assume that this situation would be far worse than the unnerving warning we
>> currently have.
> 
> I suppose you mean a situation where the static const member has been declared
> but not defined [1].  A static member variable needs to be defined *outside*
> the class body if you want to take its adress, even when it has been given an
> initializer together with its declaration *inside* the class body.
> 
> Even if we don't define FieldVector::size there is no problem.  Up until now
> it was an enumerator, so it was never possible to take its adress.  So if we
> declare it as a static const member now, this won't break anything that wasn't
> broken before.
> 
> Bye,
> Jö.
> 
> [1] Consider the following code:
> 
>     === test.hh ==========================================================
>     template<unsigned i>
>     struct A {
>       static const unsigned size = i;
>     };
> 
>     const unsigned &frob1();
>     === test.cc ==========================================================
>     #include "test.hh"
> 
>     const unsigned &frob1() {
>       return A<1>::size;
>     }
>     === main.hh ==========================================================
>     #include <iostream>
>     #include "test.hh"
> 
>     int main() {
>       std::cout << "direct: " << &A<1>::size << std::endl;
>       std::cout << "via frob: " << &frob1() << std::endl;
>     }
>     ======================================================================
> 
>     When compiled using
> 
>       g++ -Wall -g -O0 test.cc main.cc -o test
> 
>     This will yield the folloing error:
>     ======================================================================
>     cd /tmp/ && g++ -Wall -g -O0 test.cc main.cc -o test
>     /tmp/ccOALiAR.o: In function `frob1()':
>     /tmp/test.cc:4: undefined reference to `A<1u>::size'
>     /tmp/ccsrWApH.o: In function `main':
>     /tmp/main.cc:5: undefined reference to `A<1u>::size'
>     collect2: ld returned 1 exit status
>     ======================================================================
> 
>     The problem is (of course [2]) that A<i>::size has been declared but not
>     defined.  If you insert the definition
> 
>       template<unsigned i>
>       const unsigned A<i>::size;
> 
>     after the class definition in test.hh, everything works fine.
> 
> [2] (eyes rolling) C++, you are so simple...
> 
> --
> If God had intended Man to Smoke, He would have set him on Fire.
> -- fortune

-- 
Martin Nolte <nolte at mathematik.uni-freiburg.de>

Universität Freiburg                                   phone: +49-761-203-5642
Abteilung für angewandte Mathematik                    fax:   +49-761-203-5632
Hermann-Herder-Straße 10
79104 Freiburg, Germany




More information about the Dune mailing list