View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0004329 | NoesisGUI | C++ SDK | public | 2025-08-01 17:38 | 2025-09-04 12:13 |
| Reporter | juancamilo.volpe | Assigned To | jsantos | ||
| Priority | normal | Severity | block | ||
| Status | resolved | Resolution | fixed | ||
| Product Version | 3.2.8 | ||||
| Target Version | 3.2.9 | Fixed in Version | 3.2.9 | ||
| Summary | 0004329: C++ SDK NoesisApp is not compiling in VS 2017 15.9.18 | ||||
| Description | In our project we are using a specific version of VS 2017 15.9.18 and we can't change it. For example, we want to use NoesisApp examples like this in our own code and it's failing to compile giving the error in image.
Steps:
| ||||
| Attached Files | |||||
| Platform | Any | ||||
|
Fixed in r15930 Please replace the following files. CompilerTools.h (13,908 bytes)
////////////////////////////////////////////////////////////////////////////////////////////////////
// NoesisGUI - http://www.noesisengine.com
// Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __CORE_COMPILERTOOLS_H__
#define __CORE_COMPILERTOOLS_H__
#include <NsCore/Noesis.h>
namespace Noesis
{
class Symbol;
class BaseRefCounted;
template<class T> class Ptr;
NS_INTERFACE Interface;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Converts each integral constant into a unique type
////////////////////////////////////////////////////////////////////////////////////////////////////
template<int N> struct Int2Type
{
enum { Result = N };
};
typedef Int2Type<false> FalseType;
typedef Int2Type<true> TrueType;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// If-Then-Else statements
////////////////////////////////////////////////////////////////////////////////////////////////////
template<bool Cond, class Then, class Else> struct If_;
template<class Then, class Else> struct If_<true, Then, Else>
{
typedef Then Result;
};
template<class Then, class Else> struct If_<false, Then, Else>
{
typedef Else Result;
};
template<bool Cond, class Then, class Else> using If = typename If_<Cond, Then, Else>::Result;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is const-qualified
///
/// Example:
/// IsConst<MyClass>::Result -> false
/// IsConst<const MyClass>::Result -> true
/// RemoveConst<const MyClass> -> MyClass
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> class IsConst
{
template<class U> struct ConstTraits
{
enum { Result = false };
typedef U Type;
};
template<class U> struct ConstTraits<const U>
{
enum { Result = true };
typedef U Type;
};
public:
enum { Result = ConstTraits<T>::Result };
typedef typename ConstTraits<T>::Type NonConstType;
};
/// Helper variable template
template<class T> using RemoveConst = typename IsConst<T>::NonConstType;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is volatile-qualified
///
/// Example:
/// IsVolatile<MyClass>::Result -> false
/// IsVolatile<volatile MyClass>::Result -> true
/// RemoveVolatile<volatile MyClass> -> MyClass
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> class IsVolatile
{
template<class U> struct VolatileTraits
{
enum { Result = false };
typedef U Type;
};
template<class U> struct VolatileTraits<volatile U>
{
enum { Result = true };
typedef U Type;
};
public:
enum { Result = VolatileTraits<T>::Result };
typedef typename VolatileTraits<T>::Type NonVolatileType;
};
/// Helper variable templates
template<class T> using RemoveVolatile = typename IsVolatile<T>::NonVolatileType;
template<class T> using RemoveCV = RemoveVolatile<RemoveConst<T>>;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Returns true if Base is a base class of Derived, or if both types are the same
///
/// Example:
/// class Father { };
/// class Child: public Father { };
/// IsDerived<Child, Father>::Result -> true
/// IsDerived<Father, Child>::Result -> false
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived, class Base> struct IsDerived
{
enum { Result = __is_base_of(Base, Derived) };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if two types are the same
///
/// Example:
/// class Father { };
/// class Child: public Father { };
/// IsSame<Child, Father>::Result -> false
/// IsSame<Child, Child>::Result -> true
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T, class U> struct IsSame
{
enum { Result = false };
};
template<class T> struct IsSame<T, T>
{
enum { Result = true };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is a pointer type
///
/// Example:
/// IsPointer<MyClass>::Result -> false
/// IsPointer<MyClass*>::Result -> true
/// RemovePointer<MyClass*> -> MyClass
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> class IsPointer
{
template<class U> struct PointerTraits
{
enum { Result = false };
typedef U Type;
};
template<class U> struct PointerTraits<U*>
{
enum { Result = true };
typedef U Type;
};
public:
enum { Result = PointerTraits<RemoveCV<T>>::Result };
typedef typename PointerTraits<RemoveCV<T>>::Type PointedType;
};
/// Helper variable template
template<class T> using RemovePointer = typename IsPointer<T>::PointedType;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is either lvalue reference or rvalue reference
///
/// Example:
/// IsReference<MyClass>::Result -> false
/// IsReference<MyClass&>::Result -> true
/// RemoveReference<MyClass&> -> MyClass
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> class IsReference
{
template<class U> struct ReferenceTraits
{
enum { Result = false };
typedef U Type;
};
template<class U> struct ReferenceTraits<U&>
{
enum { Result = true };
typedef U Type;
};
public:
enum { Result = ReferenceTraits<T>::Result };
typedef typename ReferenceTraits<T>::Type NonReferenceType;
};
/// Helper variable template
template<class T> using RemoveReference = typename IsReference<T>::NonReferenceType;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is ref counted (derived from Interface or BaseRefCounted).
/// If Result is true, the type T can be stored inside a Ptr<>
///
/// Example:
/// IsRefCounted<int>::Result -> false
/// IsRefCounted<ICommand>::Result -> true
/// IsRefCounted<const ICommand>::Result -> true
/// IsRefCounted<Button>::Result -> true
/// IsRefCounted<const Button>::Result -> true
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsRefCounted
{
enum { Result = IsDerived<T, BaseRefCounted>::Result || IsDerived<T, Interface>::Result };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is an interface (derived from Interface but not from BaseRefCounted)
///
/// Example:
/// IsInterface<int>::Result -> false
/// IsInterface<Button>::Result -> false
/// IsInterface<ICommand>::Result -> true
/// IsInterface<const ICommand>::Result -> true
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsInterface
{
enum { Result = !IsDerived<T, BaseRefCounted>::Result && IsDerived<T, Interface>::Result };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is Ptr<>
///
/// Example:
/// IsPtr<MyClass>::Result -> false
/// IsPtr<Ptr<MyClass>>::Result -> true
/// RemovePtr<Ptr<MyClass>> -> MyClass
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> class IsPtr
{
template<class U> struct PtrTraits
{
enum { Result = false };
typedef U Type;
};
template<class U> struct PtrTraits<Ptr<U>>
{
enum { Result = true };
typedef U Type;
};
public:
enum { Result = PtrTraits<RemoveCV<T>>::Result };
typedef typename PtrTraits<RemoveCV<T>>::Type PointedType;
};
/// Helper variable template
template<class T> using RemovePtr = typename IsPtr<T>::PointedType;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if a type is a non-union class type
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsClass
{
enum { Result = __is_class(T) };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if type is an enumeration type
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsEnum
{
enum { Result = __is_enum(T) };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if type can be safely copied with memcpy
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsTriviallyCopiable
{
enum { Result = __is_trivially_copyable(T) };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if it is best to pass a type as copy or as reference
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct IsBestByCopy
{
typedef RemoveCV<T> T_;
enum
{
Result =
IsSame<T_, bool>::Result ||
IsSame<T_, char>::Result ||
IsSame<T_, signed char>::Result ||
IsSame<T_, unsigned char>::Result ||
IsSame<T_, signed short>::Result ||
IsSame<T_, unsigned short>::Result ||
IsSame<T_, signed int>::Result ||
IsSame<T_, unsigned int>::Result ||
IsSame<T_, signed long>::Result ||
IsSame<T_, unsigned long>::Result ||
IsSame<T_, signed long long>::Result ||
IsSame<T_, unsigned long long>::Result ||
IsSame<T_, Symbol>::Result ||
IsSame<T_, float>::Result ||
IsSame<T_, double>::Result ||
IsSame<T_, long double>::Result ||
IsEnum<T_>::Result ||
IsPointer<T_>::Result
};
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Calculates the type that must be used to efficiently pass T as a parameter to a function
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T> struct Param
{
typedef If<IsBestByCopy<T>::Result, T, const T&> Type;
};
template<class T> struct Param<T&>
{
typedef T& Type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// This metafunction is a convenient way to leverage SFINAE to conditionally remove functions
/// from overload resolution based on type traits and to provide separate function overloads and
/// specializations for different type traits.
////////////////////////////////////////////////////////////////////////////////////////////////////
template<bool B, class T = void> struct EnableIf_ {};
template<class T> struct EnableIf_<true, T>
{
typedef T Type;
};
template<bool B, class T = void> using EnableIf = typename EnableIf_<B,T>::Type;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Checks if the callable object F can be invoked with the specified arguments and return type
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F, class Ret, class... Args>
class IsInvocable
{
template<class T> static T&& DeclVal();
template<class U> static auto Invoke(int) -> EnableIf
<
IsSame<decltype(DeclVal<U>()(DeclVal<Args>()...)), Ret>::Result, char
>;
template<class> static long Invoke(...);
public:
enum { Result = sizeof(Invoke<F>(0)) == sizeof(char) };
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper function to force move semantics on values
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
inline constexpr RemoveReference<T>&& MoveArg(T&& arg)
{
return static_cast<RemoveReference<T>&&>(arg);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper for perfect forwarding of function arguments
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
inline constexpr T&& ForwardArg(RemoveReference<T>& arg)
{
return static_cast<T&&>(arg);
}
template<class T>
inline constexpr T&& ForwardArg(RemoveReference<T>&& arg)
{
return static_cast<T&&>(arg);
}
}
#endif
Delegate.h (6,738 bytes)
////////////////////////////////////////////////////////////////////////////////////////////////////
// NoesisGUI - http://www.noesisengine.com
// Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved.
////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __CORE_DELEGATE_H__
#define __CORE_DELEGATE_H__
#include <NsCore/Noesis.h>
#include <NsCore/CompilerTools.h>
#include <NsCore/BaseComponent.h>
#include <NsCore/Vector.h>
#include <NsCore/Ptr.h>
namespace Noesis
{
template<class T> class Delegate;
template<class T> class DelegateImpl;
////////////////////////////////////////////////////////////////////////////////////////////////////
/// A generic and efficient implementation of callbacks, an alternative to std::function:
///
/// Advantages:
/// - Faster compilation times compared to std::function
/// - Easier to debug due to simpler internal structure
/// - Fixed memory footprint (4 pointers), with no heap allocations
/// - Supports multicast (like C#) via '+=' operator (note: multicast uses dynamic memory)
/// - Delegates are comparable (e.g., for removing handlers)
///
/// Lambda Support:
/// - Standard C++ lambdas **cannot be compared** (due to unique closure types)
/// - However, we support 'lambda_ref' delegates, which store a pointer to the lambda
/// - These *can* be compared
/// - They can be used with '+=' and '-=' for multicast registration/removal
/// - The caller is responsible for keeping the lambda alive for the lifetime of the delegate
///
/// Usage Examples:
/// Delegate<uint32_t (uint32_t)> d0 = &MyReporter;
/// Delegate<uint32_t (uint32_t)> d1 = MakeDelegate(obj, &Manager::MyReporter)
/// Delegate<uint32_t (uint32_t)> d2 = [](uint32_t x) { return x + 1; };
///
/// auto lambda = [](uint32_t) { return 0; };
/// Delegate<uint32_t (uint32_t)> d3 = λ
///
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Ret, class ...Args>
class Delegate<Ret (Args...)>
{
public:
/// Constructor for empty delegates
Delegate();
/// Constructor from free function
Delegate(Ret (*func)(Args...));
/// Constructs a delegate from a lambda or functor
/// The lambda cannot be compared, so it cannot be removed from a multicast delegate
template<class F, class = EnableIf<IsInvocable<F, Ret, Args...>::Result>>
Delegate(const F& f);
/// Constructs a delegate from a lambda or functor pointer (similar to 'std::function_ref')
/// This allows comparison, so the delegate can be removed from a multicast delegate
template<class F, class = EnableIf<IsInvocable<F, Ret, Args...>::Result>>
Delegate(const F* f);
/// Constructor from class member function
template<class C> Delegate(C* obj, Ret (C::*func)(Args...));
/// Constructor from class member function (const)
template<class C> Delegate(const C* obj, Ret (C::*func)(Args...) const);
/// Constructor from ref-counted class member function
template<class C> Delegate(const Ptr<C>& obj, Ret (C::*func)(Args...));
/// Constructor from ref-counted class member function (const)
template<class C> Delegate(const Ptr<C>& obj, Ret (C::*func)(Args...) const);
/// Constructor from ref-counted class member function (const)
template<class C> Delegate(const Ptr<const C>& obj, Ret (C::*func)(Args...) const);
/// Copy constructor
Delegate(const Delegate& d);
/// Move constructor
Delegate(Delegate&& d);
/// Destructor
~Delegate();
/// Copy operator
Delegate& operator=(const Delegate& d);
/// Move operator
Delegate& operator=(Delegate&& d);
/// Reset to empty
void Reset();
/// Check if delegate is empty
bool Empty() const;
/// Boolean conversion
operator bool() const;
/// Equality
bool operator==(const Delegate& d) const;
/// Non-equality
bool operator!=(const Delegate& d) const;
/// Add delegate
void Add(const Delegate& d);
void operator+=(const Delegate& d);
/// Remove delegate
void Remove(const Delegate& d);
void operator-=(const Delegate& d);
/// Numbers of contained delegates
uint32_t Size() const;
/// Delegate invocation. For multidelegates, returned value corresponds to last invocation
Ret operator()(Args... args) const;
Ret Invoke(Args... args) const;
/// Delegate invoker for manual invocations of multidelegates items
struct Invoker: public BaseComponent
{
uint32_t Size() const;
void BeginInvoke();
Ret Invoke(uint32_t i, Args... args) const;
void EndInvoke();
void Compact();
uint16_t nestingCount = 0;
uint16_t pendingDeletes = 0;
Vector<Delegate, 2> v;
};
/// Returns the invoker of the delegate, or null for simple delegates
Invoker* GetInvoker() const;
private:
void FromFreeFunc(Ret (*func)(Args...));
template<class F> void FromFunctor(const F& f);
template<class F> void FromFunctorRef(const F* f);
template<class C> void FromMemberFunc(C* obj, Ret (C::*func)(Args...));
template<class C> void FromMemberFunc(const C* obj, Ret (C::*func)(Args...) const);
void InitNull();
bool IsNull() const;
typedef DelegateImpl<Ret (Args...)> Impl;
friend Impl;
typename Impl::Base* GetBase();
const typename Impl::Base* GetBase() const;
Delegate(typename Impl::Base* base, Int2Type<0>);
private:
alignas(void*) uint8_t data[4 * sizeof(void*)];
};
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Helper functions to deduce automatically the type when creating a delegate
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class C, class Ret , class ...Args>
Delegate<Ret (Args...)> MakeDelegate(C* obj, Ret (C::*func)(Args...));
template<class C, class Ret, class ...Args>
Delegate<Ret (Args...)> MakeDelegate(const Ptr<C>& obj, Ret (C::*func)(Args...));
template<class C, class Ret, class ...Args>
Delegate<Ret (Args...)> MakeDelegate(const C* obj, Ret (C::*func)(Args...) const);
template<class C, class Ret, class ...Args>
Delegate<Ret (Args...)> MakeDelegate(const Ptr<C>& obj, Ret (C::*func)(Args...) const);
template<class C, class Ret, class ...Args>
Delegate<Ret (Args...)> MakeDelegate(const Ptr<const C>& obj, Ret (C::*func)(Args...) const);
}
#include <NsCore/Delegate.inl>
#endif
|
|
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2025-08-01 17:38 | juancamilo.volpe | New Issue | |
| 2025-08-01 17:38 | juancamilo.volpe | File Added: image.png | |
| 2025-08-01 18:15 | sfernandez | Assigned To | => jsantos |
| 2025-08-01 18:15 | sfernandez | Status | new => assigned |
| 2025-08-01 18:15 | sfernandez | Target Version | => 3.2.9 |
| 2025-08-07 17:26 | jsantos | Note Added: 0010965 | |
| 2025-08-07 17:26 | jsantos | File Added: CompilerTools.h | |
| 2025-08-07 17:26 | jsantos | File Added: Delegate.h | |
| 2025-08-07 17:26 | jsantos | Status | assigned => resolved |
| 2025-08-07 17:26 | jsantos | Resolution | open => fixed |
| 2025-08-07 17:26 | jsantos | Fixed in Version | => 3.2.9 |
| 2025-09-04 12:13 | jsantos | Description Updated |