View Issue Details

IDProjectCategoryView StatusLast Update
0004329NoesisGUIC++ SDKpublic2025-09-04 12:13
Reporterjuancamilo.volpe Assigned Tojsantos  
PrioritynormalSeverityblock 
Status resolvedResolutionfixed 
Product Version3.2.8 
Target Version3.2.9Fixed in Version3.2.9 
Summary0004329: 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.
This is a blocker for our project to try implement our own behaviors.

NS_IMPLEMENT_REFLECTION(DropItemBehavior, "Inventory.DropItemBehavior")
{
    UIElementData* data = NsMeta<UIElementData>(TypeOf<SelfClass>());
    data->RegisterProperty<bool>(IsDragOverProperty, "IsDragOver",
        PropertyMetadata::Create(false));
    data->RegisterProperty<Ptr<BaseCommand>>(DropCommandProperty, "DropCommand",
        PropertyMetadata::Create(Ptr<BaseCommand>()));
}

NS_END_COLD_REGION

Steps:

  1. Have the Noesis Native SDK downloaded, last version 3.2.8 will work.
  2. Install VS 2017 15.9.18
  3. Open Build folder and the NoesisGUI-win-x86_64-vs2017 with VS 2017 15.9.18
  4. Try compiling NoesisApp project and see the errors.
Attached Files
image.png (39,177 bytes)   
image.png (39,177 bytes)   
PlatformAny

Activities

jsantos

jsantos

2025-08-07 17:26

manager   ~0010965

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
CompilerTools.h (13,908 bytes)   
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 = &lambda;
///
////////////////////////////////////////////////////////////////////////////////////////////////////
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
Delegate.h (6,738 bytes)   

Issue History

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