Jump to content

  • Log In with Google      Sign In   
  • Create Account

Juliean

Member Since 29 Jun 2010
Offline Last Active Today, 05:58 PM

Topics I've Started

Templated constructor "overwrites" regular copy-ctor

16 December 2014 - 04:20 PM

EDIT: Ok, I'm a dumbass. Defining the second non-const reference copy-ctor is the right way, and it only didn't support the symbol because I just switched to the test-project which didn't have a compile-dependency set for the engine-lib. Why don't you forget I asked that... I'll just leave it up though in case someone as confused as me might have a similar issue, sometimes.

 

Hello,

 

I've got a problem in a class of my engine. This is the relevant part of the class for the issue:

class __declspec(dllexport) Variable
{
public:
    template<typename Type>
    explicit Variable(Type& value);
    template<typename Type>
    explicit Variable(const Type& value);

    Variable(const Variable& variable);
}

So until now I only used to have the second templated ctor, in which as in the following code:

 

 

Variable var; Variable var2(var);

Variable var;
Variable var2(var);

The copy-ctor was being called. But now that I've also included the non-const reference templated ctor, this one gets called instead. After thinking it through this appears logical, since Type& is the closer match to being passed a "Variable&" then "const Variable&", even though this is the more specific version. So if I'm not mistaken, this at least is how c++ is supposed to behave.

 

But how can I solve this? Things I've already tried and didn't work:

 

- declaring a second "Variable(Variable& variable)" copy-ctor. MSVC will complain with a warning C4521 (second copy ctor declared) and not generate any symbol for that version, so I can't link anymore.

 

- removing the "const" from the ctor altogther. Not really a viable option from begin on, but just in case someone mentiones it. This class cannot be used that way.

 

Does somebody know any easy solution for this? There has got to be one, right? I really don't want having to do stuff like

Variable var;
Variable var2((const Variable&)var);

or

Variable copyVariable(const Variable& source)
{
    return Variable(source);
}

for this. Any suggestions, or is there no way to make him call the right copy-ctor by modifiying the declarations somehow?


Transparent backbuffer

09 October 2014 - 08:56 AM

Hello,

 

I'm trying to get a transparent backbuffer, for integrating my DX-rendered gui better with the rest of the OS. I've got a few questions/issues with that though:

 

- I've found out that I'm supposed to use DwmExtendFrameIntoClientArea for that. It also kind of works, though I get some sort of strange alpha/z-ordering issues, as you can see in Issue.png. Here is the code I'm using the create the window (plain old windows w/o any libary): (see edit below)

 

- Even though I can now see whats underneath the empty areas of my GUI... I still can't click/do anything else there, since the empty backbuffer is still overlapping the whole screen. Is there any way of "deactivating" certain areas of my backbuffer/invisible window, so that my application behaves like it was rendered using normal windows? Note that I can't just move the backbuffer as the main window you see moves, because there might be popup-windows of all sorts, which can go over the area of the main window... so any method for willingly deactivate area of a window?

 

EDIT: Ok, I was too fast in blaming the windows-part for this. Apparently the issue is with my rendering, because its those areas with the weird issues, where I render an alpha-blended texture over a solid texture. That happens for all my texts, and also for the icon in the upper left. Now I can get rid of this effect for most parts, by using alpha testing via clip (when alpha in the texture is 0), but what am I supposed to do when I have semi-transparent values, like the edges of the icon in the upper left? I can't just disable alpha-writing all together, since after clearing everything in the backbuffer is 0 (transparent). But I need to somehow only write alpha when the value is greater then what is currently in the buffer.

 

I'm rendering my gui with painters-algorithm and batched, so everything that is on top gets drawn last, in one go. Is there any way to achieve this kind of alpha-effect to fix my issue? So what I want summed up is:

 

- Every pixel with alpha > 0 should get drawn.

- In case texture pixel alpha is greater than backbuffer pixel alpha, the alpha value is written

- Otherwise, the pixel should still be blended to the content thats already in the backbuffer, but alpha value should stay the same.

 

EDIT2: Ugh, I'm just too tired to think. Of course I can configurate the AlphaSrcBlend and AlphaDestBlend-states to fig this issue. Havn't used those in a while, huh. So the rendering problems are solved now, though Issue#2 is still up. Any ideas for that?


std::unique_ptr issues

08 September 2014 - 08:06 AM

Hello,

 

I'm just in the process of replacing objects that owned and deleted a pure pointer with std::unique_ptr. However, I'm running into some issues:

 

- I've been heavily using forward declaration to speed up compile times, like here:

class Trigger;

class Instance
{
    typedef std::unordered_map<std::wstring, Trigger*> TriggerMap;
public:

    ~Instance(void)
    {
        for(auto& trigger : m_mTrigger)
        {
            delete trigger.second;
        }
    }
    
private:

    TriggerMap m_mTrigger;
}

However, I keep getting "warning C2027" in visual studio, in that an incomplete type can't be deleted when replacing the pure pointer with std::unique_ptr. Some of the times leaving the empty dtor fixes it, however in most cases, especially containers, I have to replace the forward-declaration with a direct include in the header. Is there some way around this? It really bugs me having to do this on so many occasions, could make recompile times significantly larger (already kind of a problem since I'm heavily using templates)...

class Trigger;

class Instance
{
	typedef std::unordered_map<std::wstring, std::unique_ptr<Trigger>> TriggerMap;
public:

	~Instance(void); // defined in cpp-file
	
private:

	TriggerMap m_mTrigger;
}

- I also keep getting compilation-errors with this kind of container-of-pointer setup when the class has a default copy ctor/operator. So the above example wouldn't even compile unless I put:

class Trigger;

class Instance
{
	typedef std::unordered_map<std::wstring, std::unique_ptr<Trigger>> TriggerMap;
public:

        Instance(void) = default;
        Instance(const Instance&) = delete;
	~Instance(void); // defined in cpp-file

        void operator=(const Instance&) = delete;
	
private:

	TriggerMap m_mTrigger;
}

Now I don't completely mind it, in fact I have been very sloppy about doing this before, since a class the won't compile that way shouldn't have been copyable before. Still, I wonder whether there is any shorthand to this? E.g. adding a std::unique_ptr member will automatically disable copy ctor/operator for the class, I wonder if thats possibly within a container class too?


decltype(vector<Type>) doesn't compile

31 August 2014 - 04:37 AM

Hello,

 

I have a chain of classes with a pair of templated set/get methods that require different return semantics based on the type.

float pod = GetAttribute<float>(0);
SomeClass* pObject = GetAttribute<SomeClass>(1);
std::vector<float>& vPOD = GetAttributeArray<float>(2);
const std::vector<SomeClass*>& vObjects= GetAttributeArray<SomeClass>(2);

auto & decltype seemed to do the job:

template<typename Type>
auto Variable::GetValue(void) const -> decltype(returnSemantics<Type>::value)
{
	ACL_ASSERT(m_type == getVariableType<Type>::type);
	ACL_ASSERT(m_isArray == isArray<Type>::value);

	return getObjectData<Type, isPrimitiveType<Type>::value>::GetData(m_pData, m_objectType);
}

returnSemantics is a templated struct that gets specialized for the destired return type:

template<typename Type, bool isPOD = isPrimitiveType<Type>::value>
struct returnSemantics
{
	static Type value = Type();
};

template<typename Type>
struct returnSemantics<Type, true>
{
	static Type value;
};

template<typename Type>
Type returnSemantics<Type, true>::value = Type();

template<typename Type>
struct returnSemantics<Type, false>
{
	static Type* value;
};

template<typename Type>
Type* returnSemantics<Type, false>::value = nullptr;

However, I can't seem to get this to work with the "array"-overload of the method:

template<typename Type>
auto AttributeComponent::GetAttributeArray(unsigned int slot) -> decltype(core::returnSemantics<std::vector<Type>>::value)
{
	return GetAttribute<std::vector<Type>>(slot);
}

When I use this code like in the examples above, I get:

error C2893: Funktionsvorlage 'unknown-type acl::event::AttributeComponent::GetAttributeArray(unsigned int)' konnte nicht spezialisiert werden
1>          Mit den folgenden Vorlagenargumenten:
1>          'Type=int'

which translates to something along the lines of "function template '...' could not be specialized with template arguments 'Type=int'. Why? Is there anything wrong with the decltype-usage?

decltype(core::returnSemantics<std::vector<Type>>::value)

I'm using the "Type" argument to form a vector, and use the vector as template-argument for my returnSemantics-structure... I'm using Visual Studio 2013, does anybode see the issue here?

 

EDIT: Also fails without the specific overload, even using

std::vector<float>& vTest = GetAttribute<std::vector<float>>(0);

which calls the first posted method fails with the same compilation error...


Destructor in vector called too often

19 August 2014 - 02:29 AM

Hello,

 

I recently experienced a very strange crash, which after inspecting further turned out to be caused by the destructor of a class being called one time too often in a certain vector creation. I havn't been able to fully determine the excact reason this is happening, so I hope some of you guys has a better idea of what could be going on. I'm using VS2013. This is the code that crashes:

const ecs::ComponentDeclaration& Sprite::GenerateDeclaration(void)
{
	const ecs::ComponentDeclaration::AttributeVector vAttributes = 
	{
		{ L"Texture", core::VariableType::STRING, offsetof(Sprite, stTexture), onSetTexture },
		{ L"Blending", core::VariableType::INT, offsetof(Sprite, blend) },
	}; // this line here

	static const ecs::ComponentDeclaration declaration(L"Sprite", vAttributes);

	return declaration;
}

The crash happens in the commented line, so appearently in the vector construction. Let me show you all related code:

struct ACCLIMATE_API ComponentDeclaration
{
public:
	typedef std::vector<AttributeDeclaration> AttributeVector;
		
//...
}

This is the declaration of the vector.

struct ACCLIMATE_API AttributeDeclaration
{
	typedef void(*SetCallback)(BaseComponent& component);

	AttributeDeclaration(const std::wstring& stName, core::VariableType type, size_t offset, SetCallback pCallback = nullptr);

	std::wstring stName;
	size_t offset;
	SetCallback pCallback;
	ICustomComponentAttributes* pCustom;

private:
	core::Variable m_default;
};

AttributeDeclaration::AttributeDeclaration(const std::wstring& stName, core::VariableType type, size_t offset, SetCallback pCallback) :
    stName(stName), pCallback(pCallback), m_default(type, false), pCustom(nullptr)
{
}

Thats the class that is being stored, with all related variables/methods. It stores a core::Variable class, which acts like a semi-variant data-container, which is defined as follows:

class ACCLIMATE_API Variable
{
public:
	static const unsigned int NO_OBJECT = -1;

	Variable(VariableType type, bool isArray);
	Variable(const Variable& variable);
	Variable(Variable&& variable);
	~Variable(void);

	Variable& operator=(const Variable& variable);
	Variable& operator=(Variable&& variable);

private:

	void* m_pData;
	VariableType m_type;
	bool m_isArray;
	unsigned int m_objectType;
};

Variable::Variable(VariableType type, bool isArray) :
	m_type(type), m_isArray(isArray), m_objectType(NO_OBJECT),
	m_pData(nullptr)
{
	ACL_ASSERT(m_type != VariableType::OBJECT);

	if(type != VariableType::UNKNOWN)
		m_pData = CallByTypeNoObject<newData, void*>();
}

Variable::Variable(const Variable& variable) :
	m_type(variable.m_type), m_isArray(variable.m_isArray), m_objectType(variable.m_objectType)
{
	m_pData = CopyData(variable.m_pData);
}

Variable::Variable(Variable&& variable) :
	m_type(variable.m_type), m_isArray(variable.m_isArray), m_objectType(variable.m_objectType)
{
	m_pData = variable.m_pData;

	variable.m_pData = nullptr;
	variable.m_type = VariableType::UNKNOWN;
	variable.m_objectType = NO_OBJECT;
}

Variable::~Variable(void)
{
	// just for simplicities sake - the actual deletion of the correct type is normally handled
	delete m_pData;
}

Variable& Variable::operator=(const Variable& variable)
{
	if(this != &variable)
	{
		m_type = variable.m_type;
		m_isArray = variable.m_isArray;
		m_objectType = variable.m_objectType;

		DeleteData();

		m_pData = CopyData(variable.m_pData);
	}
	
	return *this;
}

Variable& Variable::operator=(Variable&& variable)
{
	if(this != &variable)
	{
		m_type = variable.m_type;
		m_isArray = variable.m_isArray;
		m_objectType = variable.m_objectType;

		m_pData = variable.m_pData;
		variable.m_pData = nullptr;
		variable.m_type = VariableType::UNKNOWN;
		variable.m_objectType = NO_OBJECT;
	}

	return *this;
}

Now the crash happens inside this classes ctor. Obviously, m_pData is destroyed more then once. The call hierachy looks as follows:

 

- ctor of first line is being called (line in the first code snipped)

- ctor for second line is being called

- copy-ctor is called from the object of the first line

- copy-ctor is called from the object of the second line

- Destructor is called on the first object

- Destructor is called on the second object

- Destructor is called on the second object again - crash!

 

Now the reason I know that the destructor is called again, and not m_pData is somehow deleted twice is that by setting m_pData to nullptr in the destructor, the crash resolves. Also note that it is probably not an issue with the Variable-class, as the void* m_pData has already been part of the AttributeDeclaration-class before, as well as part of some other class.

 

_____________________________________________________

 

So, thats about all the information I can give. I can't make any sense of the vector-code, so debugging it further is rather out of the question. My question is now: Does someone see something obviously wrong, or knows/has some idea what is going on? Appearently I *could* fix it by simply putting in the nullptr-set in the ctor, but thats way to hackish and obviously just hides the problem. One thing I find interesting is that the move-ctor isn't called, as it is almost always when dealing with this kind of vector-emplacement, maybe thats related to the problem?

 

 


PARTNERS