C
Christopher
What would cause an call to std::map::empty() to throw an unhandled
exception?
I created an std::map with a vector of classes as a key and provided
my own comparator, following the advice in a previous post. Now when
it came time to run, I am getting an unhandled exception the very
first time I try to do anything with it.
My unhandled exception occurs on the line "if( !m_inputLayouts.empty
() )" in method "ID3D10InputLayout * InputLayoutManager::GetInputLayout
(const std::vector<InputElementDescription> inputElementDescs,
const Pass &
pass)"
The map is empty at that point, so I am not understanding why I would
get an exception.
Perhaps there is a problem with my comparator? I read over the rules
in the sgi writeup on maps and believe I implemented them.
Relevant code:
------------------------------------------------------------------------------------------------------------------------------------
#ifndef INPUTLAYOUTMANAGER_H
#define INPUTLAYOUTMANAGER_H
// EngineX Includes
#include "Graphics\3D\InputElementDescription.h"
#include "Graphics\Effects\Pass.h"
// DirectX Includes
#include <d3d10.h>
#include <d3dx10.h>
// Standard Includes
#include <vector>
#include <map>
//----------------------------------------------------------------------------
class InputLayoutManager
{
public:
/**
* Constructor
**/
InputLayoutManager(ID3D10Device & device);
/**
* Deconstructor
*/
~InputLayoutManager();
/**
* Gets or creates a D3D input layout matching the input element
description
*
* If an input layout matching the input element description has not
been requested before,
* it will be created. Creation of an input layout is costly,
therefore it is recommended to
* make an attempt to create all input layouts at init time.
**/
ID3D10InputLayout * GetInputLayout(const
std::vector<InputElementDescription> inputElementDescs,
const Pass & pass);
private:
ID3D10Device & m_device;
/**
* A map of D3D Input Layout, mapped by the Input Element
Descriptions that were used to create them
**/
struct CompareKeys
{
bool operator() (const std::vector<InputElementDescription> &
lhs,
const std::vector<InputElementDescription> &
rhs) const;
};
typedef std::map< std::vector<InputElementDescription>,
ID3D10InputLayout *, CompareKeys> InputLayoutMap;
InputLayoutMap m_inputLayouts;
};
#endif
-----------------------------------------------------------------------------------------------
#include "InputLayoutManager.h"
//----------------------------------------------------------------------------
InputLayoutManager::InputLayoutManager(ID3D10Device & device)
:
m_device(device)
{
}
//----------------------------------------------------------------------------
InputLayoutManager::~InputLayoutManager()
{
for(InputLayoutMap::iterator it = m_inputLayouts.begin(); it !=
m_inputLayouts.end(); ++it)
{
it->second->Release();
}
}
//----------------------------------------------------------------------------
ID3D10InputLayout * InputLayoutManager::GetInputLayout(const
std::vector<InputElementDescription> inputElementDescs,
const Pass &
pass)
{
// Check if the input layout already exists
if( !m_inputLayouts.empty() )
{
InputLayoutMap::iterator it = m_inputLayouts.find
(inputElementDescs);
if( it != m_inputLayouts.end() )
{
return it->second;
}
}
// Create a new input layout
D3D10_PASS_DESC passDesc = pass.GetPassDesc();
ID3D10InputLayout * inputLayout = NULL;
m_device.CreateInputLayout(&inputElementDescs[0],
inputElementDescs.size(),
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&inputLayout);
// Store the input layout
m_inputLayouts[inputElementDescs] = inputLayout;
return inputLayout;
}
//----------------------------------------------------------------------------
bool InputLayoutManager::CompareKeys:perator() (const
std::vector<InputElementDescription> & lhs,
const
std::vector<InputElementDescription> & rhs) const
{
// This is not really a "less than" operation.
// We are simply defining a way to order keys that meet the
criteria of a std::map
if( lhs.size() < rhs.size() )
{
return true;
}
else if( lhs.size() < rhs.size() )
{
return false;
}
for(unsigned i = 0; i < lhs.size(); ++i)
{
if( lhs.GetSemanticName() < rhs.GetSemanticName() )
{
return true;
}
else if( lhs.GetSemanticName() > rhs.GetSemanticName() )
{
return false;
}
if( lhs.SemanticIndex < rhs.SemanticIndex )
{
return true;
}
else if( lhs.SemanticIndex > rhs.SemanticIndex )
{
return false;
}
if( lhs.Format < rhs.Format )
{
return true;
}
else if( lhs.Format > rhs.Format )
{
return false;
}
if( lhs.InputSlot < rhs.InputSlot )
{
return true;
}
else if( lhs.InputSlot > rhs.InputSlot )
{
return false;
}
if( lhs.AlignedByteOffset < rhs.AlignedByteOffset )
{
return true;
}
else if( lhs.AlignedByteOffset > rhs.AlignedByteOffset )
{
return false;
}
if( lhs.InputSlotClass < rhs.InputSlotClass )
{
return true;
}
else if( lhs.InputSlotClass > rhs.InputSlotClass )
{
return false;
}
if( lhs.InstanceDataStepRate < rhs.InstanceDataStepRate )
{
return true;
}
else if( lhs.InstanceDataStepRate > rhs
.InstanceDataStepRate )
{
return false;
}
}
return false;
}
exception?
I created an std::map with a vector of classes as a key and provided
my own comparator, following the advice in a previous post. Now when
it came time to run, I am getting an unhandled exception the very
first time I try to do anything with it.
My unhandled exception occurs on the line "if( !m_inputLayouts.empty
() )" in method "ID3D10InputLayout * InputLayoutManager::GetInputLayout
(const std::vector<InputElementDescription> inputElementDescs,
const Pass &
pass)"
The map is empty at that point, so I am not understanding why I would
get an exception.
Perhaps there is a problem with my comparator? I read over the rules
in the sgi writeup on maps and believe I implemented them.
Relevant code:
------------------------------------------------------------------------------------------------------------------------------------
#ifndef INPUTLAYOUTMANAGER_H
#define INPUTLAYOUTMANAGER_H
// EngineX Includes
#include "Graphics\3D\InputElementDescription.h"
#include "Graphics\Effects\Pass.h"
// DirectX Includes
#include <d3d10.h>
#include <d3dx10.h>
// Standard Includes
#include <vector>
#include <map>
//----------------------------------------------------------------------------
class InputLayoutManager
{
public:
/**
* Constructor
**/
InputLayoutManager(ID3D10Device & device);
/**
* Deconstructor
*/
~InputLayoutManager();
/**
* Gets or creates a D3D input layout matching the input element
description
*
* If an input layout matching the input element description has not
been requested before,
* it will be created. Creation of an input layout is costly,
therefore it is recommended to
* make an attempt to create all input layouts at init time.
**/
ID3D10InputLayout * GetInputLayout(const
std::vector<InputElementDescription> inputElementDescs,
const Pass & pass);
private:
ID3D10Device & m_device;
/**
* A map of D3D Input Layout, mapped by the Input Element
Descriptions that were used to create them
**/
struct CompareKeys
{
bool operator() (const std::vector<InputElementDescription> &
lhs,
const std::vector<InputElementDescription> &
rhs) const;
};
typedef std::map< std::vector<InputElementDescription>,
ID3D10InputLayout *, CompareKeys> InputLayoutMap;
InputLayoutMap m_inputLayouts;
};
#endif
-----------------------------------------------------------------------------------------------
#include "InputLayoutManager.h"
//----------------------------------------------------------------------------
InputLayoutManager::InputLayoutManager(ID3D10Device & device)
:
m_device(device)
{
}
//----------------------------------------------------------------------------
InputLayoutManager::~InputLayoutManager()
{
for(InputLayoutMap::iterator it = m_inputLayouts.begin(); it !=
m_inputLayouts.end(); ++it)
{
it->second->Release();
}
}
//----------------------------------------------------------------------------
ID3D10InputLayout * InputLayoutManager::GetInputLayout(const
std::vector<InputElementDescription> inputElementDescs,
const Pass &
pass)
{
// Check if the input layout already exists
if( !m_inputLayouts.empty() )
{
InputLayoutMap::iterator it = m_inputLayouts.find
(inputElementDescs);
if( it != m_inputLayouts.end() )
{
return it->second;
}
}
// Create a new input layout
D3D10_PASS_DESC passDesc = pass.GetPassDesc();
ID3D10InputLayout * inputLayout = NULL;
m_device.CreateInputLayout(&inputElementDescs[0],
inputElementDescs.size(),
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&inputLayout);
// Store the input layout
m_inputLayouts[inputElementDescs] = inputLayout;
return inputLayout;
}
//----------------------------------------------------------------------------
bool InputLayoutManager::CompareKeys:perator() (const
std::vector<InputElementDescription> & lhs,
const
std::vector<InputElementDescription> & rhs) const
{
// This is not really a "less than" operation.
// We are simply defining a way to order keys that meet the
criteria of a std::map
if( lhs.size() < rhs.size() )
{
return true;
}
else if( lhs.size() < rhs.size() )
{
return false;
}
for(unsigned i = 0; i < lhs.size(); ++i)
{
if( lhs.GetSemanticName() < rhs.GetSemanticName() )
{
return true;
}
else if( lhs.GetSemanticName() > rhs.GetSemanticName() )
{
return false;
}
if( lhs.SemanticIndex < rhs.SemanticIndex )
{
return true;
}
else if( lhs.SemanticIndex > rhs.SemanticIndex )
{
return false;
}
if( lhs.Format < rhs.Format )
{
return true;
}
else if( lhs.Format > rhs.Format )
{
return false;
}
if( lhs.InputSlot < rhs.InputSlot )
{
return true;
}
else if( lhs.InputSlot > rhs.InputSlot )
{
return false;
}
if( lhs.AlignedByteOffset < rhs.AlignedByteOffset )
{
return true;
}
else if( lhs.AlignedByteOffset > rhs.AlignedByteOffset )
{
return false;
}
if( lhs.InputSlotClass < rhs.InputSlotClass )
{
return true;
}
else if( lhs.InputSlotClass > rhs.InputSlotClass )
{
return false;
}
if( lhs.InstanceDataStepRate < rhs.InstanceDataStepRate )
{
return true;
}
else if( lhs.InstanceDataStepRate > rhs
.InstanceDataStepRate )
{
return false;
}
}
return false;
}