Repository: microsoft/terminal
File: src/inc/til/winrt.h (C/C++)

Code before:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
    template<typename T>
    struct property
    {
        property<T>() = default;
        property<T>(T defaultValue) :
            _value{ defaultValue } {}

        T operator()() const
        {
            return _value;
        }
        void operator()(const T& value)
        {
            _value = value;
        }
        void operator()(const T&& value)
        {
            _value = value;
        }
        property<T>& operator=(const property<T>& other)
        {
            _value = other._value;
            return *this;
        }
        property<T>& operator=(const T& newValue)
        {
            _value = newValue;
            return *this;
        }

    private:
        T _value;
    };

#ifdef WINRT_Windows_Foundation_H

    template<typename ArgsT>
    struct event
    {
        event<ArgsT>() = default;
        winrt::event_token operator()(const ArgsT& handler) { return _handlers.add(handler); }
        void operator()(const winrt::event_token& token) { _handlers.remove(token); }
        template<typename... Arg>
        void raise(Arg const&... args)

Review comment (suggestion):
This doesn't work, because:
* `const T&&` is basically equivalent to `const T&`.
* `&&` is entirely fake in C++ and is basically just `&` with sugar on top. 😄 So when you declare a parameter as `T&&`, it'll not be `&&` anymore once you use it. In other words, you have to `std::move` it again.

I wrote more about these issues here: https://github.com/microsoft/terminal/pull/14807#discussion_r1104683597

Code after:
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

namespace til // Terminal Implementation Library. Also: "Today I Learned"
{
    template<typename T>
    struct property
    {
        explicit constexpr property(auto&&... args) :
            _value{ std::forward<decltype(args)>(args)... } {}

        property& operator=(const property& other) = default;

        T operator()() const
        {
            return _value;
        }
        void operator()(auto&& arg)
        {
            _value = std::forward<decltype(arg)>(arg);
        }
        operator bool() const noexcept
        {
            if constexpr (std::is_same_v<T, winrt::hstring>)
            {
                return !_value.empty();
            }
            else
            {
                return _value;
            }
        }
        bool operator==(const property& other) const noexcept
        {
            return _value == other._value;
        }
        bool operator!=(const property& other) const noexcept
        {
            return _value != other._value;
        }
        bool operator==(const T& other) const noexcept
        {
            return _value == other;
        }
        bool operator!=(const T& other) const noexcept
        {
            return _value != other;
        }