Value that doesn’t have identity and cannot be moved
От: Максим Рогожин Россия  
Дата: 23.05.19 16:52
Оценка:
Привет!

Разбираюсь с value category, читаю http://www.stroustrup.com/terminology.pdf:

iM: has identity and cannot be moved from
im: has identity and can be moved from
Im: does not have identity and can be moved from

The fourth possibility (“IM”: doesn’t have identity and cannot be moved) is not useful in C++

Я не понял есть ли в языке выражения которые относятся с категории IM?
Если есть, то хотелось бы узнать несколько примеров таких выражений.
Re: Value that doesn’t have identity and cannot be moved
От: rg45 СССР  
Дата: 23.05.19 17:09
Оценка: 8 (2)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет!


МР>Разбираюсь с value category, читаю http://www.stroustrup.com/terminology.pdf:


МР>iM: has identity and cannot be moved from

МР>im: has identity and can be moved from
МР>Im: does not have identity and can be moved from

МР>The fourth possibility (“IM”: doesn’t have identity and cannot be moved) is not useful in C++


МР>Я не понял есть ли в языке выражения которые относятся с категории IM?


Ну ясно же написано: "is not useful in C++" — как это можно еще интерпретировать?

Вот тебе картинка прямо из стандарта. Любое выражение в C++ относится к одной из трех конкретных категорий, соответствующих листьям этого графа (lvalue, xvalue, prvalue). Узлы более верхних уровней — это группировки. Так вот lvalue — это iM, xvalue — im, prvalue — Im. Узлы второго уровня: glvalue объединяет все "i", rvalue объединяет все "m". Что такое IM, мне и представить сложно — какая-то вещь в себе, которую никак нельзя использовать.

--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.05.2019 17:19 rg45 . Предыдущая версия . Еще …
Отредактировано 23.05.2019 17:17 rg45 . Предыдущая версия .
Отредактировано 23.05.2019 17:11 rg45 . Предыдущая версия .
Re[2]: Value that doesn’t have identity and cannot be moved
От: Constructor  
Дата: 07.06.19 15:30
Оценка: 7 (1)
Здравствуйте, rg45, Вы писали:

R>Что такое IM, мне и представить сложно — какая-то вещь в себе, которую никак нельзя использовать.


Если я правильно понимаю, то эту вещь всё-таки можно использовать, хотя польза от неё и не слишком велика. Скажем, есть код приблизительно такого вида:

#include <iostream>

namespace N
{
    void foo()
    {
        std::cout << "N::foo()" << std::endl;
    }
    
    void bar(const int argument)
    {
        std::cout << "N::bar(int), argument = " << argument << std::endl;
    }
}

int main()
{
    N::foo();
    N::bar(42);
    N::foo();
    N::bar(108);
    N::foo();
}


...и хочется посчитать количество вызовов всех функций в пространстве имён N (или каком-нибудь другом), внеся минимальные изменения в существующий код. Это можно сделать, вообще не изменяя кода самих функций. Например, так:

#include <iostream>

template <typename SomeType>
class Counter final
{
private:
    static auto& value() noexcept
    {
        static std::size_t counter;
        return counter;
    }
    
public:
    Counter() = delete;
    Counter(const Counter&) = delete;
    Counter(Counter&&) = delete;
    ~Counter() = delete;
    
    Counter& operator=(const Counter&) = delete;
    Counter& operator=(Counter&&) = delete;
    
    static auto Value() noexcept
    {
        return value();
    }
    
    static auto Increment() noexcept
    {
        return ++value();
    }
};

template <typename DerivedCounter>
class FunctionCallCounter
{
private:
    using InternalCounter = Counter<DerivedCounter>;
    
public:
    FunctionCallCounter() noexcept
    {
        (void)InternalCounter::Increment();
    }
    
    FunctionCallCounter(const FunctionCallCounter&) = delete;
    FunctionCallCounter(FunctionCallCounter&&) = delete;
    
    FunctionCallCounter& operator=(const FunctionCallCounter&) = delete;
    FunctionCallCounter& operator=(FunctionCallCounter&&) = delete;
    
    static auto NumberOfCalls() noexcept
    {
        return InternalCounter::Value();
    }
};

struct N final : public FunctionCallCounter<N>
{
    void foo()
    {
        std::cout << "N::foo()" << std::endl;
    }
    
    void bar(const int argument)
    {
        std::cout << "N::bar(int), argument = " << argument << std::endl;
    }
};

int main()
{
    N{}.foo();
    N{}.bar(42);
    N{}.foo();
    N{}.bar(108);
    N{}.foo();
    std::cout << "Number of function calls = " << N::NumberOfCalls() << std::endl;
}


Сущности N{} здесь как раз-таки представляют собой IM (doesn’t have identity and cannot be moved).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.