ill-formed reference to pointer

Discussion in 'C++' started by m0shbear, Jan 30, 2011.

  1. m0shbear

    m0shbear Guest

    I'm trying to use this code to check the compiler's output to see if
    the inlining is aggressive enough to use inline functions instead of
    #defines and I'm getting the following error: "invalid initialization
    of reference of type ‘const unsigned char*&’ from expression of type
    ‘u8*’".
    Does the inline lowercase match the macro uppercase?

    code:
    extern "C" {
    #include <stdint.h>
    }

    typedef uint8_t u8;
    typedef uint64_t u64be;

    template <typename T>
    struct itype {
    typedef T value;
    typedef T& reference;
    typedef T const& const_reference;
    typedef T* pointer;
    typedef T const* const_pointer;
    };

    #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    const,src); (src) += 8

    template<typename T, typename P> inline T* ptr_cast(P* p) { return
    reinterpret_cast<T*>(p); }

    inline void xf64(itype<u8>::pointer dst,
    itype<itype<u8>::const_pointer>::reference src) {
    *ptr_cast<u64be>(dst) ^= *ptr_cast<u64be const>(src); src += 8;
    }

    int main() {
    u8 fop[64], foq[64], fos[64],fot[64];
    u8* foP=fop;
    u8* foQ=foq;
    u8* foS=fos;
    u8* foT=fot;
    xf64(foP,foQ);
    XF64(foS, foT);
    }
    m0shbear, Jan 30, 2011
    #1
    1. Advertising

  2. m0shbear

    Ian Collins Guest

    On 01/30/11 06:03 PM, m0shbear wrote:
    > I'm trying to use this code to check the compiler's output to see if
    > the inlining is aggressive enough to use inline functions instead of
    > #defines


    It's highly unlikely that you would have to resort to macros, unless
    your compiler is very old and scummy.

    > and I'm getting the following error: "invalid initialization
    > of reference of type ‘const unsigned char*&’ from expression of type
    > ‘u8*’".


    That's right, the types don't match.

    > Does the inline lowercase match the macro uppercase?


    Not really, macro arguments don't have types.

    > code:
    > extern "C" {
    > #include<stdint.h>
    > }


    You shouldn't have to add the extern "C" here.

    > typedef uint8_t u8;
    > typedef uint64_t u64be;


    These are horrible!

    > template<typename T>
    > struct itype {
    > typedef T value;
    > typedef T& reference;
    > typedef T const& const_reference;
    > typedef T* pointer;
    > typedef T const* const_pointer;
    > };
    >
    > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))


    Why do this?

    > #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > const,src); (src) += 8
    >
    > template<typename T, typename P> inline T* ptr_cast(P* p) { return
    > reinterpret_cast<T*>(p); }


    Or this?

    --
    Ian Collins
    Ian Collins, Jan 30, 2011
    #2
    1. Advertising

  3. m0shbear

    m0shbear Guest

    On Jan 30, 12:38 am, Ian Collins <> wrote:
    > On 01/30/11 06:03 PM, m0shbear wrote:
    >
    > > I'm trying to use this code to check the compiler's output to see if
    > > the inlining is aggressive enough to use inline functions instead of
    > > #defines

    >
    > It's highly unlikely that you would have to resort to macros, unless
    > your compiler is very old and scummy.
    >
    > > and I'm getting the following error: "invalid initialization
    > > of reference of type const unsigned char*& from expression of type
    > > u8* ".

    >
    > That's right, the types don't match.
    >
    > > Does the inline lowercase match the macro uppercase?

    >
    > Not really, macro arguments don't have types.
    >
    > > code:
    > > extern "C" {
    > > #include<stdint.h>
    > > }

    >
    > You shouldn't have to add the extern "C" here.
    >
    > > typedef uint8_t u8;
    > > typedef uint64_t u64be;

    >
    > These are horrible!


    I use the 'be' suffix to note that the variable is explictly big-
    endian instead of native-endian. Why is that bad?

    >
    > > template<typename T>
    > > struct itype {
    > >    typedef T value;
    > >    typedef T&  reference;
    > >    typedef T const&  const_reference;
    > >    typedef T* pointer;
    > >    typedef T const* const_pointer;
    > > };

    >
    > > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > Why do this?


    Long symbol names become annoying to read, and reinterpret_cast is
    used enough that creating a wrapper macro for it is clearer.

    >
    > > #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > > const,src); (src) += 8


    The macro I'm trying to convert into an inline function.
    What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    bytes, to minimize the amount of instructions generated. And the C++
    version of the C-style cast maps to reinterpret_cast.

    Now why does the compiler auto-constify any non-const pointer used as
    the second argument in memcpy() but refuses to do so here?



    > > template<typename T, typename P>  inline T* ptr_cast(P* p) { return
    > > reinterpret_cast<T*>(p); }


    A somewhat typesafe version of PTR_CAST.
    m0shbear, Jan 30, 2011
    #3
  4. m0shbear

    m0shbear Guest

    On Jan 30, 12:58 am, m0shbear <> wrote:
    > On Jan 30, 12:38 am, Ian Collins <> wrote:
    >
    >
    >
    > > On 01/30/11 06:03 PM, m0shbear wrote:

    >
    > > > I'm trying to use this code to check the compiler's output to see if
    > > > the inlining is aggressive enough to use inline functions instead of
    > > > #defines

    >
    > > It's highly unlikely that you would have to resort to macros, unless
    > > your compiler is very old and scummy.

    >
    > > > and I'm getting the following error: "invalid initialization
    > > > of reference of type const unsigned char*& from expression of type
    > > > u8* ".

    >
    > > That's right, the types don't match.

    >
    > > > Does the inline lowercase match the macro uppercase?

    >
    > > Not really, macro arguments don't have types.

    >
    > > > code:
    > > > extern "C" {
    > > > #include<stdint.h>
    > > > }

    >
    > > You shouldn't have to add the extern "C" here.

    >
    > > > typedef uint8_t u8;
    > > > typedef uint64_t u64be;

    >
    > > These are horrible!

    >
    > I use the 'be' suffix to note that the variable is explictly big-
    > endian instead of native-endian. Why is that bad?
    >
    >
    >
    > > > template<typename T>
    > > > struct itype {
    > > >    typedef T value;
    > > >    typedef T&  reference;
    > > >    typedef T const&  const_reference;
    > > >    typedef T* pointer;
    > > >    typedef T const* const_pointer;
    > > > };

    >
    > > > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > > Why do this?

    >
    > Long symbol names become annoying to read, and reinterpret_cast is
    > used enough that creating a wrapper macro for it is clearer.
    >
    >
    >
    > > > #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > > > const,src); (src) += 8

    >
    > The macro I'm trying to convert into an inline function.
    > What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    > bytes, to minimize the amount of instructions generated. And the C++
    > version of the C-style cast maps to reinterpret_cast.
    >
    > Now why does the compiler auto-constify any non-const pointer used as
    > the second argument in memcpy() but refuses to do so here?


    Ugh. G++ can constify or make-reference, but can't automagically do
    the former then the latter. Is there a workaround?
    m0shbear, Jan 30, 2011
    #4
  5. m0shbear

    Ian Collins Guest

    On 01/30/11 06:58 PM, m0shbear wrote:
    > On Jan 30, 12:38 am, Ian Collins<> wrote:
    >> On 01/30/11 06:03 PM, m0shbear wrote:
    >>
    >>> typedef uint8_t u8;
    >>> typedef uint64_t u64be;

    >>
    >> These are horrible!

    >
    > I use the 'be' suffix to note that the variable is explictly big-
    > endian instead of native-endian. Why is that bad?


    I guess that's OK, but the typedef doesn't give you any protection form
    mixing u64be and uint64_t types.

    >>> template<typename T>
    >>> struct itype {
    >>> typedef T value;
    >>> typedef T& reference;
    >>> typedef T const& const_reference;
    >>> typedef T* pointer;
    >>> typedef T const* const_pointer;
    >>> };

    >>
    >>> #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >>
    >> Why do this?

    >
    > Long symbol names become annoying to read, and reinterpret_cast is
    > used enough that creating a wrapper macro for it is clearer.


    Using reinterpret_cast anything other than infrequently should set alarm
    bells wringing.

    >>> #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    >>> const,src); (src) += 8

    >
    > The macro I'm trying to convert into an inline function.
    > What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    > bytes, to minimize the amount of instructions generated. And the C++
    > version of the C-style cast maps to reinterpret_cast.


    Why don't you just write

    template <typename S, typename D>
    void xf64( S* dst, const D* src )
    {
    *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    uint64_t*>(src);
    src += 8;
    }

    Which is closer to your macro?

    It either case, things could turn nasty if the pointers aren't correctly
    aligned for uint64_t.

    > Now why does the compiler auto-constify any non-const pointer used as
    > the second argument in memcpy() but refuses to do so here?


    Because the parameter is a reference.

    --
    Ian Collins
    Ian Collins, Jan 30, 2011
    #5
  6. On Jan 29, 9:58 pm, m0shbear <> wrote:
    > On Jan 30, 12:38 am, Ian Collins <> wrote:
    > > On 01/30/11 06:03 PM, m0shbear wrote:
    > > > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > > Why do this?

    >
    > Long symbol names become annoying to read, and reinterpret_cast is
    > used enough that creating a wrapper macro for it is clearer.


    Meh. I'm going to have to disagree. First, reinterpret_cast ought to
    be rare enough that this isn't even an issue. static_cast and
    dynamic_cast, or fix your likely broken code, please.

    Second, I think it's really poor form to wrap any standard library
    feature or function. It's just obfuscation.
    Joshua Maurice, Jan 30, 2011
    #6
  7. m0shbear

    m0shbear Guest

    On Jan 30, 2:20 am, Ian Collins <> wrote:
    > On 01/30/11 06:58 PM, m0shbear wrote:
    >
    > > On Jan 30, 12:38 am, Ian Collins<>  wrote:
    > >> On 01/30/11 06:03 PM, m0shbear wrote:

    >
    > >>> typedef uint8_t u8;
    > >>> typedef uint64_t u64be;

    >
    > >> These are horrible!

    >
    > > I use the 'be' suffix to note that the variable is explictly big-
    > > endian instead of native-endian. Why is that bad?

    >
    > I guess that's OK, but the typedef doesn't give you any protection form
    > mixing u64be and uint64_t types.


    It's like a #define which evaluates to nothing - it serves more as a
    pre-/post-condition note than a compiler verifiable pre-/post-
    condition.

    >
    > >>> template<typename T>
    > >>> struct itype {
    > >>>     typedef T value;
    > >>>     typedef T&    reference;
    > >>>     typedef T const&    const_reference;
    > >>>     typedef T* pointer;
    > >>>     typedef T const* const_pointer;
    > >>> };

    >
    > >>> #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > >> Why do this?

    >
    > > Long symbol names become annoying to read, and reinterpret_cast is
    > > used enough that creating a wrapper macro for it is clearer.

    >
    > Using reinterpret_cast anything other than infrequently should set alarm
    > bells wringing.
    >


    It's only in the bitwise portion of the inner loop. It was faster to
    macro it and I was too lazy to regex it via s/Ptr_cast<([a-z0-9_]+ ?
    const?)>/reinterpret_cast<\1>/g.


    > >>> #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > >>> const,src); (src) += 8

    >
    > > The macro I'm trying to convert into an inline function.
    > > What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    > > bytes, to minimize the amount of instructions generated. And the C++
    > > version of the C-style cast maps to reinterpret_cast.

    >
    > Why don't you just write
    >
    > template <typename S, typename D>
    > void xf64( S* dst, const D* src )
    > {
    >    *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    > uint64_t*>(src);
    >    src += 8;
    >
    > }
    >
    > Which is closer to your macro?


    Nope: src will be unchanged since it's copied by value instead of by
    reference.
    In the macro, the ability to assume that the src token is a reference
    is a precondition.

    In any case, the function's arguments are (uint8_t *, const uint8_t
    *), so it works. I was just playing around with constness and
    references and got bit.

    >
    > It either case, things could turn nasty if the pointers aren't correctly
    > aligned for uint64_t.


    Indeed, which is why I'm making a padding wrapper for unaligned xor,
    one of the reasons being the ability to add simd intrinsics at a later
    time. Not all cpus support unaligned 64/128-bit load-store between mem
    and simd reg(s).

    >
    > > Now why does the compiler auto-constify any non-const pointer used as
    > > the second argument in memcpy() but refuses to do so here?

    >
    > Because the parameter is a reference.


    References do a damn good job of killing off C tricks I've learned
    over the years :p
    m0shbear, Jan 30, 2011
    #7
  8. m0shbear

    m0shbear Guest

    On Jan 30, 3:03 am, Joshua Maurice <> wrote:
    > On Jan 29, 9:58 pm, m0shbear <> wrote:
    >
    > > On Jan 30, 12:38 am, Ian Collins <> wrote:
    > > > On 01/30/11 06:03 PM, m0shbear wrote:
    > > > > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > > > Why do this?

    >
    > > Long symbol names become annoying to read, and reinterpret_cast is
    > > used enough that creating a wrapper macro for it is clearer.

    >
    > Meh. I'm going to have to disagree. First, reinterpret_cast ought to
    > be rare enough that this isn't even an issue. static_cast and
    > dynamic_cast, or fix your likely broken code, please.
    >
    > Second, I think it's really poor form to wrap any standard library
    > feature or function. It's just obfuscation.


    Polymorphic casting is unused - dynamic_cast is unsuitable;
    The goal is pointer coercion in order to grab the bits - static_cast
    is unsuitable.
    Static_cast would also not work for returning function pointers from
    dlopen or run-time named parameters.
    m0shbear, Jan 30, 2011
    #8
  9. m0shbear

    Ian Collins Guest

    On 01/30/11 09:26 PM, m0shbear wrote:
    > On Jan 30, 2:20 am, Ian Collins<> wrote:
    >> On 01/30/11 06:58 PM, m0shbear wrote:
    >>> On Jan 30, 12:38 am, Ian Collins<> wrote:
    >>>> On 01/30/11 06:03 PM, m0shbear wrote:

    >
    >>>>> #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    >>>>> const,src); (src) += 8

    >>
    >>> The macro I'm trying to convert into an inline function.
    >>> What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    >>> bytes, to minimize the amount of instructions generated. And the C++
    >>> version of the C-style cast maps to reinterpret_cast.

    >>
    >> Why don't you just write
    >>
    >> template<typename S, typename D>
    >> void xf64( S* dst, const D* src )
    >> {
    >> *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    >> uint64_t*>(src);
    >> src += 8;
    >>
    >> }
    >>
    >> Which is closer to your macro?

    >
    > Nope: src will be unchanged since it's copied by value instead of by
    > reference.
    > In the macro, the ability to assume that the src token is a reference
    > is a precondition.


    > In any case, the function's arguments are (uint8_t *, const uint8_t
    > *), so it works. I was just playing around with constness and
    > references and got bit.


    OK,

    const uint8_t* xf64( uint8_t* dst, const uint8_t* src )
    {
    *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    uint64_t*>(src);
    return src + 8;
    }

    But wouldn't you want both src and dst to advance?

    >>> Now why does the compiler auto-constify any non-const pointer used as
    >>> the second argument in memcpy() but refuses to do so here?

    >>
    >> Because the parameter is a reference.

    >
    > References do a damn good job of killing off C tricks I've learned
    > over the years :p


    You'd hit the same problem with pointers to pointers.

    --
    Ian Collins
    Ian Collins, Jan 30, 2011
    #9
  10. m0shbear wrote, On 30.1.2011 6:03:
    > I'm trying to use this code to check the compiler's output to see if
    > the inlining is aggressive enough to use inline functions instead of
    > #defines and I'm getting the following error: "invalid initialization
    > of reference of type ‘const unsigned char*&’ from expression of type
    > ‘u8*’".
    > Does the inline lowercase match the macro uppercase?
    >
    > code:
    > extern "C" {
    > #include <stdint.h>
    > }
    >
    > typedef uint8_t u8;
    > typedef uint64_t u64be;
    >
    > template <typename T>
    > struct itype {
    > typedef T value;
    > typedef T& reference;
    > typedef T const& const_reference;
    > typedef T* pointer;
    > typedef T const* const_pointer;
    > };
    >
    > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))
    >
    > #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > const,src); (src) += 8
    >
    > template<typename T, typename P> inline T* ptr_cast(P* p) { return
    > reinterpret_cast<T*>(p); }
    >
    > inline void xf64(itype<u8>::pointer dst,
    > itype<itype<u8>::const_pointer>::reference src) {
    > *ptr_cast<u64be>(dst) ^= *ptr_cast<u64be const>(src); src += 8;
    > }
    >
    > int main() {
    > u8 fop[64], foq[64], fos[64],fot[64];
    > u8* foP=fop;
    > u8* foQ=foq;
    > u8* foS=fos;
    > u8* foT=fot;
    > xf64(foP,foQ);
    > XF64(foS, foT);

    Do you realise that casting from this u8* to u64be* and then accessing the
    value as if it were u64be* is undefined behaviour?

    > }


    --
    VH
    Vaclav Haisman, Jan 30, 2011
    #10
  11. m0shbear

    m0shbear Guest

    On Jan 30, 4:44 am, Ian Collins <> wrote:
    > On 01/30/11 09:26 PM, m0shbear wrote:
    >
    >
    >
    > > On Jan 30, 2:20 am, Ian Collins<>  wrote:
    > >> On 01/30/11 06:58 PM, m0shbear wrote:
    > >>> On Jan 30, 12:38 am, Ian Collins<>    wrote:
    > >>>> On 01/30/11 06:03 PM, m0shbear wrote:

    >
    > >>>>> #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > >>>>> const,src); (src) += 8

    >
    > >>> The macro I'm trying to convert into an inline function.
    > >>> What I'm doing is a wordsize-optimized endian-agnostic XOR of a set of
    > >>> bytes, to minimize the amount of instructions generated. And the C++
    > >>> version of the C-style cast maps to reinterpret_cast.

    >
    > >> Why don't you just write

    >
    > >> template<typename S, typename D>
    > >> void xf64( S* dst, const D* src )
    > >> {
    > >>     *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    > >> uint64_t*>(src);
    > >>     src += 8;

    >
    > >> }

    >
    > >> Which is closer to your macro?

    >
    > > Nope: src will be unchanged since it's copied by value instead of by
    > > reference.
    > > In the macro, the ability to assume that the src token is a reference
    > > is a precondition.
    > > In any case, the function's arguments are (uint8_t *, const uint8_t
    > > *), so it works. I was just playing around with constness and
    > > references and got bit.

    >
    > OK,
    >
    > const uint8_t* xf64( uint8_t* dst, const uint8_t* src )
    > {
    >    *reinterpret_cast<uint64_t*>(dst) ^= *reinterpret_cast<const
    > uint64_t*>(src);
    >    return src + 8;
    >
    > }
    >
    > But wouldn't you want both src and dst to advance?


    Suppose dst points to a memory-mapped register, and src to an array.
    Then dst points to the xor-reduction of src.

    The goal is to evaulate the expression, where [x:y] is byte range:
    *dst = *src[0:7] ^ *src[8:15] ^ ... ^ *src[n-8:n-1].

    So it is useful to advance src, but not dst.

    However, the double-or-nothing approach is also useful. This allows
    for the elimination of the reference and simply use a pointer, and do
    the post-increment of src in parallel with the increment of the loop
    counter. It will also potentially stop enough off-by-one errors to
    make it worth spending a minute re-coding.

    > >>> Now why does the compiler auto-constify any non-const pointer used as
    > >>> the second argument in memcpy() but refuses to do so here?

    >
    > >> Because the parameter is a reference.

    >
    > > References do a damn good job of killing off C tricks I've learned
    > > over the years :p

    >
    > You'd hit the same problem with pointers to pointers.


    Actually, no. I've managed to hack it into working with const_cast and
    reinterpret_cast.
    m0shbear, Jan 30, 2011
    #11
  12. m0shbear

    m0shbear Guest

    On Jan 30, 5:12 am, Vaclav Haisman <> wrote:
    > m0shbear wrote, On 30.1.2011 6:03:
    >
    > > I'm trying to use this code to check the compiler's output to see if
    > > the inlining is aggressive enough to use inline functions instead of
    > > #defines and I'm getting the following error: "invalid initialization
    > > of reference of type ‘const unsigned char*&’ from expression of type
    > > ‘u8*’".
    > > Does the inline lowercase match the macro uppercase?

    >
    > > code:
    > > extern "C" {
    > > #include <stdint.h>
    > > }

    >
    > > typedef uint8_t u8;
    > > typedef uint64_t u64be;

    >
    > > template <typename T>
    > > struct itype {
    > >    typedef T value;
    > >    typedef T& reference;
    > >    typedef T const& const_reference;
    > >    typedef T* pointer;
    > >    typedef T const* const_pointer;
    > > };

    >
    > > #define PTR_CAST(T, p) (reinterpret_cast<T*>(p))

    >
    > > #define XF64(dst,src) *PTR_CAST(u64be,dst) ^= *PTR_CAST(u64be
    > > const,src); (src) += 8

    >
    > > template<typename T, typename P> inline T* ptr_cast(P* p) { return
    > > reinterpret_cast<T*>(p); }

    >
    > > inline void xf64(itype<u8>::pointer dst,
    > > itype<itype<u8>::const_pointer>::reference src) {
    > >    *ptr_cast<u64be>(dst) ^= *ptr_cast<u64be const>(src); src += 8;
    > > }

    >
    > > int main() {
    > >    u8 fop[64], foq[64], fos[64],fot[64];
    > >    u8* foP=fop;
    > >    u8* foQ=foq;
    > >    u8* foS=fos;
    > >    u8* foT=fot;
    > >    xf64(foP,foQ);
    > >    XF64(foS, foT);

    >
    > Do you realise that casting from this u8* to u64be* and then accessing the
    > value as if it were u64be* is undefined behaviour?
    >


    A contiguous region of memory is a contiguous region of memory. If the
    address is 8/16-aligned, going from byte access to 64-bit access has a
    noticeable performance boost. It's like using 64-bit copy/cmp in mem/
    strXXX() for aligned bytes and falling back to 8-bit after alignment.
    m0shbear, Jan 30, 2011
    #12
    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. Replies:
    0
    Views:
    3,029
  2. Ill-formed program

    , Dec 4, 2008, in forum: C++
    Replies:
    1
    Views:
    403
  3. Johannes Schaub (litb)

    Is this using-declaration ill-formed?

    Johannes Schaub (litb), Aug 16, 2010, in forum: C++
    Replies:
    6
    Views:
    330
    James Kanze
    Aug 17, 2010
  4. SG
    Replies:
    5
    Views:
    669
  5. K. Frank
    Replies:
    1
    Views:
    334
    K. Frank
    Nov 6, 2011
Loading...

Share This Page