PDA

View Full Version : Strange compile error in template class which occurs for certain function calls


Shree
10-28-2007, 02:46 PM
I have a templated class (IsosurfaceOctreeVolume) which contains a pointer to another templated class (OctreeVolume), The start of the class definition is shown below:


template <class T>
class IsosurfaceOctreeVolume : public PrimitiveCommon
{
const OctreeVolume<T>* octdata;


For the 4 function calls made using this pointer below I get the following gcc compiler error "error: ISO C++ forbids comp arison between pointer and integer":

octdata->lookup_neighbor<0,0,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
octdata->lookup_neighbor<0,1,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
octdata->lookup_neighbor<1,0,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
octdata->lookup_neighbor<1,1,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);

However, these 3 calls also using exactly the same pointer do not generate an error:

octdata->lookup_neighbor<1,1,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);
octdata->lookup_neighbor<1,0,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);
octdata->lookup_neighbor<0,1,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);

Looking at the above 7 calls there seems to be a problem when the 3rd (last) template argument being passed to OctreeVolume::lookup_neighbor has the value 1 instead of 0.

The complete code for function lookup_neighbor (which is a member function of the templated class OctreeVolume) is listed below:


template <typename T>
template<bool CHECK_X, bool CHECK_Y, bool CHECK_Z>
inline T OctreeVolume<T>::lookup_neighbor(Vec3i& cell, Vec3i& offset, int stop_depth, int depth, unsigned int* index_trace) const
{
Vec3i target_neighbor = cell + offset;
int child_bit;

//recurse up the tree until we find a parent that contains both cell and target_neighbor
for(int up = depth; up >= 0; up--)
{
child_bit = child_bit_depth[up];

if (CHECK_X && CHECK_Y && CHECK_Z)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_X && CHECK_Y)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_X && CHECK_Z)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_Y && CHECK_Z)
{
if ( ((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_X)
{
if ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit))
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_Y)
{
if ((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit))
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
else if (CHECK_Z)
{
if ((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit))
return lookup_node(target_neighbor, stop_depth, up, index_trace[up]);
}
}

child_bit = max_depth_bit;
if (CHECK_X && CHECK_Y && CHECK_Z)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_X && CHECK_Y)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_X && CHECK_Z)
{
if ( ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_Y && CHECK_Z)
{
if ( ((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_X)
{
if ((target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit))
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_Y)
{
if ((target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit))
return lookup_node(target_neighbor, stop_depth, 0, 0);
}
else if (CHECK_Z)
{
if ((target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit))
return lookup_node(target_neighbor, stop_depth, 0, 0);
}

return 0;
}


If I explicitly specify the type of the OctreeVolume (as shown below) then the error disappears:


namespace Manta
{
template <class T>
class IsosurfaceOctreeVolume : public PrimitiveCommon
{
const OctreeVolume<float>* octdata;


So declaring the pointer to be of type OctreeVolume<T> instead of OctreeVolume<float> or some other explicit type is somehow causing the above error. However, strangely it only affects 4 out of the 7 possible function calls.

Does anyone have any idea why this is happening and what the problem is?:wallbash:

.oisyn
10-28-2007, 04:06 PM
I suppose you're getting the error INSIDE the lookup_neighbor() function? See your compiler output for the exact details, and post them here.

Btw, you can severely reduce the code (and improve maintainability) in that function by using a single if.
if ( (!CHECK_X || (target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
(!CHECK_Y || (target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
(!CHECK_Z || (target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )

Shree
10-29-2007, 04:08 AM
I suppose you're getting the error INSIDE the lookup_neighbor() function? See your compiler output for the exact details, and post them here.

My bad - sorry.

The error occurs when the lookup_neighbour function is called from within members functions of the IsoSurfaceOctreeVolume class.

Below is the actual compiler output (with errors) for one of these functions. (e.g IsoSurfaceOctreeVolume::single_traverse_leaf)


Building CXX object Model/CMakeFiles/Manta_Model.dir/Primitives/IsosurfaceOctreeVolume.o
/home/shree/dev/Manta/Model/Primitives/IsosurfaceOctreeVolume.h: In member function ‘bool Manta::IsosurfaceOctreeVolume<T>::single_traverse_leaf(Manta::RayPacket&, int, const Manta::Vector&, const Manta::Vector&, const Manta::Vector&, int, int, int, T, Manta::Vec3i&, unsigned int*, Manta::Vec3i&, float, float) const’:
/home/shree/dev/Manta/Model/Primitives/IsosurfaceOctreeVolume.h:753: error: ISO C++ forbids comparison between pointer and integer
/home/shree/dev/Manta/Model/Primitives/IsosurfaceOctreeVolume.h:765: error: ISO C++ forbids comparison between pointer and integer
/home/shree/dev/Manta/Model/Primitives/IsosurfaceOctreeVolume.h:777: error: ISO C++ forbids comparison between pointer and integer
/home/shree/dev/Manta/Model/Primitives/IsosurfaceOctreeVolume.h:813: error: ISO C++ forbids comparison between pointer and integer


The 4 calls to lookup_neighbour which generate these errors can be found in the section of the code (from IsoSurfaceOctreeVolume::single_traverse_leaf) below, immediately following the 4 comments :

//0,0,1
//0,1,1
//1,1,1
//1,0,1



#ifdef USE_OCTREE_DATA
//use octree data
float rho[2][2][2];
T min_rho, max_rho, this_rho;
min_rho = max_rho = this_rho = scalar;
rho[0][0][0] = static_cast<float>(this_rho);
Vec3i offset(0,0,child_bit);

//0,0,1
if (target_child & 1)
{
this_rho = octdata->lookup_neighbor<0,0,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[0][0][1] = static_cast<float>(this_rho);

//0,1,1
offset.data[1] = child_bit;
if (target_child & 3)
{
this_rho = octdata->lookup_neighbor<0,1,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[0][1][1] = static_cast<float>(this_rho);

//1,1,1
offset.data[0] = child_bit;
if (target_child & 7)
{
this_rho = octdata->lookup_neighbor<1,1,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[1][1][1] = static_cast<float>(this_rho);

//1,1,0
offset.data[2] = 0;
if (target_child & 6)
{
this_rho = octdata->lookup_neighbor<1,1,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[1][1][0] = static_cast<float>(this_rho);

//1,0,0
offset.data[1] = 0;
if (target_child & 4)
{
this_rho = octdata->lookup_neighbor<1,0,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[1][0][0] = static_cast<float>(this_rho);

//1,0,1
offset.data[2] = child_bit;
if (target_child & 5)
{
this_rho = octdata->lookup_neighbor<1,0,1>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[1][0][1] = static_cast<float>(this_rho);

//0,1,0
offset.data[0] = 0;
offset.data[1] = child_bit;
offset.data[2] = 0;
if (target_child & 2)
{
this_rho = octdata->lookup_neighbor<0,1,0>(child_cell, offset, stop_depth, leaf_depth, index_trace);
min_rho = MIN(min_rho, this_rho);
max_rho = MAX(max_rho, this_rho);
}
else
this_rho = scalar;
rho[0][1][0] = static_cast<float>(this_rho);
#else

Shree
10-29-2007, 04:09 AM
Btw, you can severely reduce the code (and improve maintainability) in that function by using a single if.
if ( (!CHECK_X || (target_neighbor.data[0] & child_bit) == (cell.data[0] & child_bit)) &&
(!CHECK_Y || (target_neighbor.data[1] & child_bit) == (cell.data[1] & child_bit)) &&
(!CHECK_Z || (target_neighbor.data[2] & child_bit) == (cell.data[2] & child_bit)) )

Thanks for this! I will do so :yes: