Elegant way to initialize non-static array member

Discussion in 'C++' started by mathieu, Nov 6, 2007.

  1. mathieu

    mathieu Guest

    Hi,

    Consider the following (*). Is there a way to rewrite it so that it
    remains convenient (N is being recomputed when array v is modified)
    *and* compiles :)

    Thanks,
    -Mathieu

    (*)
    template <typename T, unsigned int N>
    struct Functor
    {
    T values[N];
    };

    int main()
    {
    const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    const unsigned int N = sizeof(v) / sizeof(v[0]);
    Functor<double,N> f = v; // will not compile
    //Functor<double,7> f = { {0, 1, 4, 9, 16, 25, 36 } }; // need to
    compute 7 by hand...

    return 0;
    }
    mathieu, Nov 6, 2007
    #1
    1. Advertising

  2. mathieu

    mathieu Guest

    On Nov 6, 3:32 pm, mathieu <> wrote:
    > Hi,
    >
    > Consider the following (*). Is there a way to rewrite it so that it
    > remains convenient (N is being recomputed when array v is modified)
    > *and* compiles :)
    >
    > Thanks,
    > -Mathieu
    >
    > (*)
    > template <typename T, unsigned int N>
    > struct Functor
    > {
    > T values[N];
    >
    > };
    >
    > int main()
    > {
    > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > const unsigned int N = sizeof(v) / sizeof(v[0]);
    > Functor<double,N> f = v; // will not compile
    > //Functor<double,7> f = { {0, 1, 4, 9, 16, 25, 36 } }; // need to
    > compute 7 by hand...
    >
    > return 0;
    >
    > }


    Super-ugly solution:

    #define V {0, 1, 4, 9, 16, 25, 36 }
    int main()
    {
    const double v[] = V;
    const unsigned int N = sizeof(v) / sizeof(v[0]);
    Functor<double,N> f = { V };
    ....
    }
    mathieu, Nov 6, 2007
    #2
    1. Advertising

  3. mathieu wrote:
    > Hi,
    >
    > Consider the following (*). Is there a way to rewrite it so that it
    > remains convenient (N is being recomputed when array v is modified)
    > *and* compiles :)
    >
    > Thanks,
    > -Mathieu
    >
    > (*)
    > template <typename T, unsigned int N>
    > struct Functor
    > {
    > T values[N];
    > };


    Add this function:

    template<class T, unsigned N> Functor<T,N> makeFunctor(T (&a)[N])
    {
    Functor<T,N> f;
    std::copy(a, a+N, f.values);
    return f;
    }

    >
    > int main()
    > {
    > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > const unsigned int N = sizeof(v) / sizeof(v[0]);
    > Functor<double,N> f = v; // will not compile
    > //Functor<double,7> f = { {0, 1, 4, 9, 16, 25, 36 } }; // need to
    > compute 7 by hand...


    Functor<double,N> f = makeFunctor(v);

    >
    > return 0;
    > }


    Final code:

    template <typename T, unsigned int N>
    struct Functor
    {
    T values[N];
    };

    #include <algorithm>
    template <typename T, unsigned int N>
    Functor<T,N> makeFunctor(T const (&a)[N])
    {
    Functor<T,N> f;
    std::copy(a, a + N, f.values);
    return f;
    }

    int main()
    {
    const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    const unsigned int N = sizeof(v) / sizeof(v[0]);

    Functor<double,N> f = makeFunctor(v);

    return 0;
    }

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 6, 2007
    #3
  4. mathieu

    mathieu Guest

    On Nov 6, 3:51 pm, "Victor Bazarov" <> wrote:
    > mathieu wrote:
    > > Hi,

    >
    > > Consider the following (*). Is there a way to rewrite it so that it
    > > remains convenient (N is being recomputed when array v is modified)
    > > *and* compiles :)


    ....

    > Final code:
    >
    > template <typename T, unsigned int N>
    > struct Functor
    > {
    > T values[N];
    > };
    >
    > #include <algorithm>
    > template <typename T, unsigned int N>
    > Functor<T,N> makeFunctor(T const (&a)[N])
    > {
    > Functor<T,N> f;
    > std::copy(a, a + N, f.values);
    > return f;
    > }
    >
    > int main()
    > {
    > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > const unsigned int N = sizeof(v) / sizeof(v[0]);
    >
    > Functor<double,N> f = makeFunctor(v);
    >
    > return 0;
    > }


    nice and simple !

    Thanks,
    -Mathieu
    mathieu, Nov 6, 2007
    #4
  5. mathieu

    terminator Guest

    On Nov 6, 6:18 pm, mathieu <> wrote:
    > On Nov 6, 3:51 pm, "Victor Bazarov" <> wrote:
    >
    > > mathieu wrote:
    > > > Hi,

    >
    > > > Consider the following (*). Is there a way to rewrite it so that it
    > > > remains convenient (N is being recomputed when array v is modified)
    > > > *and* compiles :)

    >
    > ...
    >
    >
    >
    >
    >
    > > Final code:

    >
    > > template <typename T, unsigned int N>
    > > struct Functor
    > > {
    > > T values[N];
    > > };

    >
    > > #include <algorithm>
    > > template <typename T, unsigned int N>
    > > Functor<T,N> makeFunctor(T const (&a)[N])
    > > {
    > > Functor<T,N> f;
    > > std::copy(a, a + N, f.values);
    > > return f;
    > > }

    >
    > > int main()
    > > {
    > > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > > const unsigned int N = sizeof(v) / sizeof(v[0]);

    >
    > > Functor<double,N> f = makeFunctor(v);

    >
    > > return 0;
    > > }

    >
    > nice and simple !
    >
    > Thanks,
    > -Mathieu- Hide quoted text -
    >
    > - Show quoted text -


    sorry to terminate, but this 'assigning to default constructed' not
    initializing.
    OP`s ugly solution is more efficient if 'T' has none-trivial
    constructors.

    regards,
    FM.
    terminator, Nov 6, 2007
    #5
  6. mathieu

    peter koch Guest

    On 6 Nov., 18:13, terminator <> wrote:
    > On Nov 6, 6:18 pm, mathieu <> wrote:
    >
    >
    >
    >
    >
    > > On Nov 6, 3:51 pm, "Victor Bazarov" <> wrote:

    >
    > > > mathieu wrote:
    > > > > Hi,

    >
    > > > > Consider the following (*). Is there a way to rewrite it so that it
    > > > > remains convenient (N is being recomputed when array v is modified)
    > > > > *and* compiles :)

    >
    > > ...

    >
    > > > Final code:

    >
    > > > template <typename T, unsigned int N>
    > > > struct Functor
    > > > {
    > > > T values[N];
    > > > };

    >
    > > > #include <algorithm>
    > > > template <typename T, unsigned int N>
    > > > Functor<T,N> makeFunctor(T const (&a)[N])
    > > > {
    > > > Functor<T,N> f;
    > > > std::copy(a, a + N, f.values);
    > > > return f;
    > > > }

    >
    > > > int main()
    > > > {
    > > > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > > > const unsigned int N = sizeof(v) / sizeof(v[0]);

    >
    > > > Functor<double,N> f = makeFunctor(v);

    >
    > > > return 0;
    > > > }

    >
    > > nice and simple !

    >
    > > Thanks,
    > > -Mathieu- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > sorry to terminate, but this 'assigning to default constructed' not
    > initializing.

    No. It is copyconstructing.

    > OP`s ugly solution is more efficient if 'T' has none-trivial
    > constructors.


    No. Not if any modern (less than say 10 years old) C++ compiler is
    used.

    >
    > regards,
    peter koch, Nov 6, 2007
    #6
  7. mathieu

    mathieu Guest

    On Nov 6, 6:28 pm, peter koch <> wrote:
    > On 6 Nov., 18:13, terminator <> wrote:
    >
    > > On Nov 6, 6:18 pm, mathieu <> wrote:

    >
    > > > On Nov 6, 3:51 pm, "Victor Bazarov" <> wrote:

    >
    > > > > mathieu wrote:
    > > > > > Hi,

    >
    > > > > > Consider the following (*). Is there a way to rewrite it so that it
    > > > > > remains convenient (N is being recomputed when array v is modified)
    > > > > > *and* compiles :)

    >
    > > > ...

    >
    > > > > Final code:

    >
    > > > > template <typename T, unsigned int N>
    > > > > struct Functor
    > > > > {
    > > > > T values[N];
    > > > > };

    >
    > > > > #include <algorithm>
    > > > > template <typename T, unsigned int N>
    > > > > Functor<T,N> makeFunctor(T const (&a)[N])
    > > > > {
    > > > > Functor<T,N> f;
    > > > > std::copy(a, a + N, f.values);
    > > > > return f;
    > > > > }

    >
    > > > > int main()
    > > > > {
    > > > > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > > > > const unsigned int N = sizeof(v) / sizeof(v[0]);

    >
    > > > > Functor<double,N> f = makeFunctor(v);

    >
    > > > > return 0;
    > > > > }

    >
    > > > nice and simple !

    >
    > > > Thanks,
    > > > -Mathieu- Hide quoted text -

    >
    > > > - Show quoted text -

    >
    > > sorry to terminate, but this 'assigning to default constructed' not
    > > initializing.

    >
    > No. It is copyconstructing.
    >
    > > OP`s ugly solution is more efficient if 'T' has none-trivial
    > > constructors.

    >
    > No. Not if any modern (less than say 10 years old) C++ compiler is
    > used.


    Those kind of questions always kills me. I never learn assembly, and I
    would have no way to know that std::copy is indeed doing the right
    thing in this case. Any clue on how to see that ?

    Thanks
    -Mathieu
    mathieu, Nov 6, 2007
    #7
  8. mathieu wrote:
    > On Nov 6, 6:28 pm, peter koch <> wrote:
    >> On 6 Nov., 18:13, terminator <> wrote:
    >> [..]
    >>> OP`s ugly solution is more efficient if 'T' has none-trivial
    >>> constructors.

    >>
    >> No. Not if any modern (less than say 10 years old) C++ compiler is
    >> used.

    >
    > Those kind of questions always kills me. I never learn assembly, and I
    > would have no way to know that std::copy is indeed doing the right
    > thing in this case. Any clue on how to see that ?


    Not sure what you mean by "the right thing", but std::copy will most
    likely do 'memcpy' on arrays of POD, which is usually quite efficient;
    as to non-trivial constructors, I believe 'terminator' is referring to
    the inefficiency due to assigning that 'std::copy' has to do. Although
    there is no way to tell whether it's inefficient until it is measured
    in a real-world situation.

    The problem with the macro solution is the symbol 'V' you have to live
    with in the program. It is global, it has no type, and if you have to
    have several of those, you quickly pollute the translation unit with
    those identifiers. It's more difficult to read as well (since the 'V'
    macro lives separately from the places where it is used).

    Theoretical inefficiency versus code maintainability... It's a common
    issue with which software designers have to deal every day.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 6, 2007
    #8
  9. mathieu

    Alex Vinokur Guest

    On Nov 6, 4:51 pm, "Victor Bazarov" <> wrote:
    [snip]
    > Final code:
    >
    > template <typename T, unsigned int N>
    > struct Functor
    > {
    > T values[N];
    > };
    >
    > #include <algorithm>
    > template <typename T, unsigned int N>
    > Functor<T,N> makeFunctor(T const (&a)[N])
    > {
    > Functor<T,N> f;
    > std::copy(a, a + N, f.values);
    > return f;
    > }
    >
    > int main()
    > {
    > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > const unsigned int N = sizeof(v) / sizeof(v[0]);
    >

    -----------------------------------------------
    Here Microsoft Visual C++ 2005 produces an error
    > Functor<double,N> f = makeFunctor(v);

    -----------------------------------------------
    >
    > return 0;
    > }

    [snip]


    Microsoft Visual C++ 2005 produces the following error
    =========================
    C2440: 'initializing' : cannot convert from 'Functor<T,N>' to
    'Functor<T,N>'
    with
    [
    T=const double,
    N=7
    ]
    and
    [
    T=double,
    N=7
    ]
    No user-defined-conversion operator available that can perform
    this conversion, or the operator cannot be called
    =============================================

    Alex Vinokur
    email: alex DOT vinokur AT gmail DOT com
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Nov 7, 2007
    #9
  10. Alex Vinokur wrote:
    > On Nov 6, 4:51 pm, "Victor Bazarov" <> wrote:
    > [snip]
    >> Final code:
    >>
    >> template <typename T, unsigned int N>
    >> struct Functor
    >> {
    >> T values[N];
    >> };
    >>
    >> #include <algorithm>
    >> template <typename T, unsigned int N>
    >> Functor<T,N> makeFunctor(T const (&a)[N])
    >> {
    >> Functor<T,N> f;
    >> std::copy(a, a + N, f.values);
    >> return f;
    >> }
    >>
    >> int main()
    >> {
    >> const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    >> const unsigned int N = sizeof(v) / sizeof(v[0]);
    >>

    > -----------------------------------------------
    > Here Microsoft Visual C++ 2005 produces an error
    >> Functor<double,N> f = makeFunctor(v);

    > -----------------------------------------------
    >>
    >> return 0;
    >> }

    > [snip]
    >
    >
    > Microsoft Visual C++ 2005 produces the following error
    > =========================
    > C2440: 'initializing' : cannot convert from 'Functor<T,N>' to
    > 'Functor<T,N>'
    > with
    > [
    > T=const double,
    > N=7
    > ]
    > and
    > [
    > T=double,
    > N=7
    > ]
    > No user-defined-conversion operator available that can perform
    > this conversion, or the operator cannot be called
    > =============================================
    >
    > Alex Vinokur
    > email: alex DOT vinokur AT gmail DOT com
    > http://mathforum.org/library/view/10978.html
    > http://sourceforge.net/users/alexvn


    Good to know.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Nov 7, 2007
    #10
  11. mathieu

    terminator Guest

    On Nov 7, 9:16 am, Alex Vinokur <> wrote:
    > On Nov 6, 4:51 pm, "Victor Bazarov" <> wrote:
    > [snip]
    >
    >
    >
    > > Final code:

    >
    > > template <typename T, unsigned int N>
    > > struct Functor
    > > {
    > > T values[N];
    > > };

    >
    > > #include <algorithm>
    > > template <typename T, unsigned int N>
    > > Functor<T,N> makeFunctor(T const (&a)[N])
    > > {
    > > Functor<T,N> f;
    > > std::copy(a, a + N, f.values);
    > > return f;
    > > }

    >
    > > int main()
    > > {
    > > const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    > > const unsigned int N = sizeof(v) / sizeof(v[0]);

    >
    > -----------------------------------------------
    > Here Microsoft Visual C++ 2005 produces an error> Functor<double,N> f = makeFunctor(v);
    >
    > -----------------------------------------------
    >
    > > return 0;
    > > }

    >
    > [snip]
    >
    > Microsoft Visual C++ 2005 produces the following error
    > =========================
    > C2440: 'initializing' : cannot convert from 'Functor<T,N>' to
    > 'Functor<T,N>'
    > with
    > [
    > T=const double,
    > N=7
    > ]
    > and
    > [
    > T=double,
    > N=7
    > ]
    > No user-defined-conversion operator available that can perform
    > this conversion, or the operator cannot be called
    > =============================================


    Why are not we going to treat intrinsic arrays as distinct coy
    constructible types?
    They can simply be fancied as some intrinsic template.

    regards,
    FM.
    terminator, Nov 7, 2007
    #11
  12. mathieu

    Alex Vinokur Guest

    On Nov 7, 4:47 pm, "Victor Bazarov"
    [snip]
    > Good to know.

    [snip]


    Compiler aCC has a probblem with this program too.

    ============= foo.cpp =============

    #include <algorithm>
    using namespace std;

    template <typename T, unsigned int N>
    struct Functor
    {
    T values[N];
    };

    template<typename T, unsigned int N>
    Functor<T,N> makeFunctor(T (&a)[N])
    {
    Functor<T,N> f;
    copy(a, a + N, f.values);
    return f;
    }

    int main()
    {
    const double v[] = {0, 1, 4, 9, 16, 25, 36 };
    const unsigned int N = sizeof(v) / sizeof(v[0]);

    Functor<double,N> f = makeFunctor(v);

    return 0;
    }


    ===================================



    aCC: HP C/aC++ B3910B A.06.13 [Nov 27 2006]
    ============= Compilation =============
    "foo.cpp", line 5: warning #2368-D: class "Functor<const double, 7U>"
    defines no constructor to initialize the following:
    const member "Functor<T, N>::values [with T=const double,
    N=7U]"
    struct Functor
    ^
    detected during instantiation of class "Functor<T, N> [with
    T=const double, N=7U]" at line 23

    "foo.cpp", line 23: error #2312: no suitable user-defined conversion
    from "Functor<const double, 7U>" to "Functor<double, 7U>" exists
    Functor<double,N> f = makeFunctor(v);
    ^

    "foo.cpp", line 13: error #2369-D: variable "f" has an uninitialized
    const or reference member
    Functor<T,N> f;
    ^
    detected during instantiation of "Functor<T, N>
    makeFunctor(T (&)[N]) [with T=const double, N=7U]" at line 23

    "/opt/aCC/include_std/algorithm", line 2023: error #2137: expression
    must be a modifiable lvalue
    *__result = *__first;
    ^
    detected during:
    instantiation of "_OutputIter std::copy(_InputIter,
    _InputIter, _OutputIter) [with _InputIter=const double *,
    _OutputIter=const double *]" at line 14 of "foo.cpp"
    instantiation of "Functor<T, N> makeFunctor(T (&)[N])
    [with T=const double, N=7U]" at line 23 of "foo.cpp"

    3 errors detected in the compilation of "foo.cpp".
    =======================================


    Alex Vinokur
    email: alex DOT vinokur AT gmail DOT com
    http://mathforum.org/library/view/10978.html
    http://sourceforge.net/users/alexvn
    Alex Vinokur, Nov 8, 2007
    #12
  13. mathieu

    James Kanze Guest

    On Nov 7, 5:07 pm, terminator <> wrote:

    [...]
    > Why are not we going to treat intrinsic arrays as distinct coy
    > constructible types?


    Because that would break C compatibility.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Nov 8, 2007
    #13
  14. mathieu

    terminator Guest

    On Nov 8, 1:27 pm, James Kanze <> wrote:
    > On Nov 7, 5:07 pm, terminator <> wrote:
    >
    > [...]
    >
    > > Why are not we going to treat intrinsic arrays as distinct coy
    > > constructible types?

    >
    > Because that would break C compatibility.
    >


    including castability to appropariate pointers will remove any
    incompatibilities .The internal interface of intrinsic array can be :

    template <typename T, unsigned size_t n>
    struct ___intrinsic_array{

    ___intrinsic_array(const ___intrinsic_array&);

    typedef const T* ___CP;
    typedef T* ___NP;
    typedef volatile T* ___VP;

    typedef const T& ___CR;
    typedef T& ___NR;
    typedef volatile T& ___VR;

    inline operator ___CP()const
    {return reinterpret_cast<___CP>(this);};
    inline operator ___NP ()
    {return reinterpret_cast<___NP >(this);};
    inline operator ___VP()volatile
    {return reinterpret_cast<___VP>(this);};

    inline ___CR operator[](const size_t& i)const
    {return *(operator ___CP()+i);};
    inline ___NR operator[](const size_t& i)
    {return *(operator ___NP()+i);};
    inline ___VR operator[](const size_t& i)volatile
    {return *(operator ___VP()+i);};

    //assignment and construction can be defined as well.

    };

    regards,
    FM.
    terminator, Nov 10, 2007
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. cppaddict
    Replies:
    16
    Views:
    19,773
    m_pahlevanzadeh
    Jul 11, 2012
  2. Replies:
    3
    Views:
    844
    Peter_Julian
    Oct 10, 2005
  3. mathieu
    Replies:
    2
    Views:
    554
    mathieu
    Nov 8, 2007
  4. dolphin
    Replies:
    3
    Views:
    1,339
    Pete Becker
    Dec 5, 2007
  5. Terry Michaels
    Replies:
    4
    Views:
    165
    w_a_x_man
    Oct 16, 2010
Loading...

Share This Page