Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

typedef float float4[4]; std::vector<float4>; does not compile, why?

19 views
Skip to first unread message

Brian Cole

unread,
May 18, 2009, 6:12:15 PM5/18/09
to
The following code will not compile in gcc 4.3.2 on Ubuntu 8.10

#include <vector>

typedef float float4[4];

int main()
{
std::vector<float4> vals;
}

I get the following compilation error:
/usr/include/c++/4.3/bits/stl_construct.h: In function ‘void
std::_Destroy(_Tp*) [with _Tp = float [4]]’:
/usr/include/c++/4.3/bits/stl_construct.h:103: instantiated from
‘void
std::_Destroy(_ForwardIterator, _ForwardIterator) [with
_ForwardIterator =
float (*)[4]]’
/usr/include/c++/4.3/bits/stl_construct.h:128: instantiated from
‘void
std::_Destroy(_ForwardIterator, _ForwardIterator,
std::allocator<_T2>&) [with
_ForwardIterator = float (*)[4], _Tp = float [4]]’
/usr/include/c++/4.3/bits/stl_vector.h:300: instantiated from
‘std::vector<_Tp, _Alloc>::~vector() [with _Tp = float [4], _Alloc =
std::allocator<float [4]>]’
test_float4.cpp:7: instantiated from here
/usr/include/c++/4.3/bits/stl_construct.h:88: error: request for
member ‘~float
[4]’ in ‘* __pointer’, which is of non-class type ‘float [4]’

The code does compile in gcc 3.4 and gcc 4.1. So I'm guessing this is
because of some "enlightened" understanding of the C++ standard?
Please enlighten me.

Thanks
-Brian

Alf P. Steinbach

unread,
May 18, 2009, 6:36:34 PM5/18/09
to
* Brian Cole:

> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>
> #include <vector>
>
> typedef float float4[4];
>
> int main()
> {
> std::vector<float4> vals;
> }
>
> I get the following compilation error:
> /usr/include/c++/4.3/bits/stl_construct.h: In function �void
> std::_Destroy(_Tp*) [with _Tp = float [4]]�:
> /usr/include/c++/4.3/bits/stl_construct.h:103: instantiated from
> �void

> std::_Destroy(_ForwardIterator, _ForwardIterator) [with
> _ForwardIterator =
> float (*)[4]]�
> /usr/include/c++/4.3/bits/stl_construct.h:128: instantiated from
> �void

> std::_Destroy(_ForwardIterator, _ForwardIterator,
> std::allocator<_T2>&) [with
> _ForwardIterator = float (*)[4], _Tp = float [4]]�
> /usr/include/c++/4.3/bits/stl_vector.h:300: instantiated from
> �std::vector<_Tp, _Alloc>::~vector() [with _Tp = float [4], _Alloc =
> std::allocator<float [4]>]�

> test_float4.cpp:7: instantiated from here
> /usr/include/c++/4.3/bits/stl_construct.h:88: error: request for
> member �~float
> [4]� in �* __pointer�, which is of non-class type �float [4]�

>
> The code does compile in gcc 3.4 and gcc 4.1. So I'm guessing this is
> because of some "enlightened" understanding of the C++ standard?
> Please enlighten me.

The element type of a standard container must be copyable.

A raw array isn't.

Curiously, the code above compiles with Comeau Online, which appears to be a bug
in Comeau (considering that it aims to catch most errors).

Try this:


<code>
#include <vector>

typedef float float4[4];

int main()
{
std::vector<float4> vals;

float4 v = {};
vals.push_back( v );
}
</code>

It should not compile.


Cheers & hth.,

- Alf

--
Due to hosting requirements I need visits to <url: http://alfps.izfree.com/>.
No ads, and there is some C++ stuff! :-) Just going there is good. Linking
to it is even better! Thanks in advance!

SG

unread,
May 19, 2009, 4:01:25 AM5/19/09
to
On 19 Mai, 00:12, Brian Cole <col...@gmail.com> wrote:
> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>
> #include <vector>
>
> typedef float float4[4];
>
> int main()
> {
>   std::vector<float4> vals;
> }

As Alf said, float4 doesn't satisfy the vector templates' requirements
as a value type.

If your C++ implementation ships with the TR1 library extension or you
can install some TR1 implementation and/or Boost you could solve this
problem via:

typedef std::tr1::array<float,4> float4;

Cheers!
SG

Brian Cole

unread,
May 19, 2009, 12:15:51 PM5/19/09
to

Apparently GCC considers this a bug (http://gcc.gnu.org/bugzilla/
show_bug.cgi?id=40192). So now I'm doubly confused.

I'm not a language lawyer, is "float4" a pointer to an array of 4
floats? Or is it an array of 4 floats? Basically if we define float4_t
as "struct float4_t { float x,y,z,w; };" is std::vector<float4>
equivalent to std::vector<float4_t> or std::vector<float4_t *>.

Thanks,
Brian

Jeff Schwab

unread,
May 19, 2009, 12:34:22 PM5/19/09
to
Brian Cole wrote:
> On May 19, 2:01 am, SG <s.gesem...@gmail.com> wrote:
>> On 19 Mai, 00:12, Brian Cole <col...@gmail.com> wrote:
>>
>>> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>>> #include <vector>
>>> typedef float float4[4];
>>> int main()
>>> {
>>> std::vector<float4> vals;
>>> }
>> As Alf said, float4 doesn't satisfy the vector templates' requirements
>> as a value type.
>>
>> If your C++ implementation ships with the TR1 library extension or you
>> can install some TR1 implementation and/or Boost you could solve this
>> problem via:
>>
>> typedef std::tr1::array<float,4> float4;

> Apparently GCC considers this a bug (http://gcc.gnu.org/bugzilla/


> show_bug.cgi?id=40192). So now I'm doubly confused.

It wasn't a bug. They should not have "fixed" it.

> I'm not a language lawyer, is "float4" a pointer to an array of 4
> floats? Or is it an array of 4 floats?

It's an array (in your original post). C++ raw arrays decay to
pointers, but that's not something you should need to worry about unless
you're manually laying out memory. You almost never should need a raw
array. Forget about raw arrays.

> Basically if we define float4_t
> as "struct float4_t { float x,y,z,w; };" is std::vector<float4>
> equivalent to std::vector<float4_t> or std::vector<float4_t *>.

Neither. std::vector<float[4]> shouldn't even be legal.

Brian Cole

unread,
May 19, 2009, 12:47:44 PM5/19/09
to

FYI, the reason this arose is because I am toying with the OpenCL
libraries which defines the type: http://www.khronos.org/registry/cl/api/1.0/cl_platform.h

If it truly is illegal I think OpenCL should change the definition to
a struct to be friendlier with C++.

-Brian

Jeff Schwab

unread,
May 19, 2009, 1:18:29 PM5/19/09
to

Khronos probably should have defined:

struct float4 { float values[4]; }

In C, though, it is common to use arrays directly as containers, for
historical reasons, and OpenCL is apparently based on C99. OpenCL is
full of other C-related nastiness, too; for example, it defines names
like float4 directly in the global namespace. Namespace pollution is a
real problem in large programs.

One easy way around the vector<float4> problem is to wrap float4 in your
own class.

blargg

unread,
May 19, 2009, 1:32:15 PM5/19/09
to
Brian Cole wrote:
> On May 19, 2:01 am, SG <s.gesem...@gmail.com> wrote:
>> On 19 Mai, 00:12, Brian Cole <col...@gmail.com> wrote:
>>
>>> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>>> #include <vector>
>>> typedef float float4[4];
[...]

> I'm not a language lawyer, is "float4" a pointer to an array of 4
> floats? Or is it an array of 4 floats?

It's the type as the object below, declared the same as the typedef but
without the word "typedef":

float float4[4];

An array is a type. Similar to how a pointer can be implicitly converted
into a bool (null = false, non-null = true), an array can be implicitly
converted into a pointer to its first element. The only place an apparent
array really is a pointer is in a function parameter or return value.

Like Jeff Schwab said, avoid arrays an instead use std::vector or
std::tr1::array.

Chris M. Thomasson

unread,
May 19, 2009, 1:40:18 PM5/19/09
to
"Brian Cole" <col...@gmail.com> wrote in message
news:652f9330-ecf8-4b0b...@d25g2000prn.googlegroups.com...

> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>
> #include <vector>
>
> typedef float float4[4];
>
> int main()
> {
> std::vector<float4> vals;
> }
>
> I get the following compilation error:


Try something like this:
_____________________________________________________________________
#include <cstdio>
#include <cstddef>
#include <cassert>
#include <vector>


template<typename T, std::size_t T_size>
class array {
T m_buffer[T_size];

public:
enum constant {
SIZE = T_size
};


T& operator [] (std::size_t size) {
assert(size < T_size);
return m_buffer[size];
}


T const& operator [] (std::size_t size) const {
assert(size < T_size);
return m_buffer[size];
}


T* get() {
return m_buffer;
}


T const* get() const {
return m_buffer;
}
};


typedef array<unsigned, 4> float4;


int main() {
std::vector<float4> v;

v.push_back(float4());
v.push_back(float4());

v[0][0] = 1;
v[0][1] = 2;
v[0][2] = 3;
v[0][3] = 4;

v[1][0] = 5;
v[1][1] = 6;
v[1][2] = 7;
v[1][3] = 8;

std::size_t c1;
std::vector<float4>::iterator i;

for (i = v.begin(), c1 = 0; i != v.end(); ++i, ++c1) {
for (std::size_t c2 = 0; c2 < float4::SIZE; ++c2) {
std::printf("v[%u][%u] == %u\n", c1, c2, v[c1][c2]);
}
}

return 0;
}
_____________________________________________________________________

Does that work for you?

Chris M. Thomasson

unread,
May 19, 2009, 1:49:19 PM5/19/09
to
"Chris M. Thomasson" <n...@spam.invalid> wrote in message
news:guuqts$2evh$1...@news.ett.com.ua...

> "Brian Cole" <col...@gmail.com> wrote in message
> news:652f9330-ecf8-4b0b...@d25g2000prn.googlegroups.com...
>> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
>>
>> #include <vector>
>>
>> typedef float float4[4];
>>
>> int main()
>> {
>> std::vector<float4> vals;
>> }
>>
>> I get the following compilation error:
>
>
> Try something like this:
> _____________________________________________________________________
> [...]> std::size_t c1;

> std::vector<float4>::iterator i;
>
> for (i = v.begin(), c1 = 0; i != v.end(); ++i, ++c1) {
> for (std::size_t c2 = 0; c2 < float4::SIZE; ++c2) {
> std::printf("v[%u][%u] == %u\n", c1, c2, v[c1][c2]);
> }
> }
>
> return 0;
> }
> _____________________________________________________________________
>
> [...]


Ummm.... I don't know why I did the iteration that way. Perhaps I should
actually use the damn iterator object `i'!!! Here, let me try again:


T* get() {
return m_buffer;
}

v.push_back(float4());
v.push_back(float4());

std::size_t c1;
std::vector<float4>::const_iterator i;

for (i = v.begin(), c1 = 0; i != v.end(); ++i, ++c1) {
for (std::size_t c2 = 0; c2 < float4::SIZE; ++c2) {

std::printf("v[%u][%u] == %u\n", c1, c2, (*i)[c2]);
}
}

return 0;
}
_____________________________________________________________________

There... That's better. I mean, the first posted program works, but its
retarded! Sorry about that.

Brian Cole

unread,
May 19, 2009, 1:55:03 PM5/19/09
to

There is a C++ wrapper layer being developed on top of OpenCL:
http://www.khronos.org/registry/cl/api/1.0/cl.hpp It will be part of
the 1.1 standard.

This is perhaps a nastiness that should be dealt with there now that I
am thoroughly convinced that cl_float4 does not play nice with C++.

-Brian

Jeff Schwab

unread,
May 19, 2009, 2:17:25 PM5/19/09
to

That may be. It looks like they're at least thinking along the right
lines, using custom vector and size_t types to wrap arrays:

template <typename T, int N>
struct vector
{
T value_[N];

operator T* () { return value_; }
operator const T* () const { return value_; }

T& operator [](int index) { return value_[index]; }
T operator [](int index) const { return value_[index]; }
};

} // namespace detail

/*!
* \brief size_t class used to interface between C++ and
* OpenCL C calls that require arrays of size_t values, who's
* size is known statically.
*/
template <int N>
struct size_t : public detail::vector< ::size_t, N> { };

James Kanze

unread,
May 20, 2009, 4:07:13 AM5/20/09
to
On May 19, 6:34 pm, Jeff Schwab <j...@schwabcenter.com> wrote:
> Brian Cole wrote:
> > On May 19, 2:01 am, SG <s.gesem...@gmail.com> wrote:
> >> On 19 Mai, 00:12, Brian Cole <col...@gmail.com> wrote:

> >>> The following code will not compile in gcc 4.3.2 on Ubuntu 8.10
> >>> #include <vector>
> >>> typedef float float4[4];
> >>> int main()
> >>> {
> >>> std::vector<float4> vals;
> >>> }
> >> As Alf said, float4 doesn't satisfy the vector templates'
> >> requirements as a value type.

> >> If your C++ implementation ships with the TR1 library
> >> extension or you can install some TR1 implementation and/or
> >> Boost you could solve this problem via:

> >> typedef std::tr1::array<float,4> float4;
> > Apparently GCC considers this a bug (http://gcc.gnu.org/bugzilla/
> > show_bug.cgi?id=40192). So now I'm doubly confused.

> It wasn't a bug. They should not have "fixed" it.

In C++03, it's a quality of implementation issue. The standard
says it's undefined behavior. And while the instantiation of
the vector works (I don't know why) in both g++ and VC++, you
can't do anything with it---none of the member functions work.
From a QoI point of view, the error should be detected by the
compiler if possible.

In C++0x, IIUC, it will require a diagnostic (unless arrays are
somehow MoveConstructable---I'm not too sure about the
implications of rvalue references with regards to arrays).

> > I'm not a language lawyer, is "float4" a pointer to an array
> > of 4 floats? Or is it an array of 4 floats?

> It's an array (in your original post). C++ raw arrays decay
> to pointers, but that's not something you should need to worry
> about unless you're manually laying out memory. You almost
> never should need a raw array. Forget about raw arrays.

Yes. In this context, as far as I can tell, the array doesn't
decay into a pointer. If it did, the template instantation
would be legal---but would be the exact equivalent of
std::vector< float* >.

About the only use for raw arrays I know is in order to obtain
static initialization and automatic calculation of the size.

> > Basically if we define float4_t
> > as "struct float4_t { float x,y,z,w; };" is std::vector<float4>
> > equivalent to std::vector<float4_t> or std::vector<float4_t *>.

> Neither. std::vector<float[4]> shouldn't even be legal.

It isn't legal. It's undefined behavior.

--
James Kanze (GABI Software) email:james...@gmail.com
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

0 new messages