Ресолвинг неоднозначностей концептов
От: vdimas Россия  
Дата: 25.11.22 10:22
Оценка:
Привет, коллеги.

Сугубо из любопытства вопрос, есть ли возможность разресолвить неоднозначность в концептах тут:
#include <concepts>

template<typename T>
concept has_foo = 
    requires(const T& a) {
        a.foo();
    };

template<typename T>
concept has_boo = 
    requires(const T& a) {
        a.boo();
    };

template<has_foo T>
void func(const T& a) {
    a.foo();
}

template<has_boo T>
void func(const T& a) {
    a.boo();
}

struct A {
    void foo() const {}
};

struct B {
    void boo() const {}
};

struct C {
    void foo() const {}
    void boo() const {}
};

void test() {
    A a;
    B b;
    C c;

    func(a);
    func(b);
    func(c);  // неоднозначность
}


Т.е. есть ли возможность явно указать версию func без обертки такого рода:

template<has_foo T>
struct Fooable {
    const T & obj_;

    Fooable(const T & obj) 
        : obj_(obj) 
    {}

    void foo() const { 
        obj_.foo(); 
    }
};

...

func(Fooable(c));

?
Re: Ресолвинг неоднозначностей концептов
От: rg45 СССР  
Дата: 25.11.22 10:49
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Привет, коллеги.


V>Сугубо из любопытства вопрос, есть ли возможность разресолвить неоднозначность в концептах тут:

V>
  пример
V>
V>#include <concepts>

V>template<typename T>
V>concept has_foo = 
V>    requires(const T& a) {
V>        a.foo();
V>    };

V>template<typename T>
V>concept has_boo = 
V>    requires(const T& a) {
V>        a.boo();
V>    };

V>template<has_foo T>
V>void func(const T& a) {
V>    a.foo();
V>}

V>template<has_boo T>
V>void func(const T& a) {
V>    a.boo();
V>}

V>struct A {
V>    void foo() const {}
V>};

V>struct B {
V>    void boo() const {}
V>};

V>struct C {
V>    void foo() const {}
V>    void boo() const {}
V>};

V>void test() {
V>    A a;
V>    B b;
V>    C c;

V>    func(a);
V>    func(b);
V>    func(c);  // неоднозначность
V>}
V>



Ну, самое просто, наверное, это добавить дополнительный констрейнт в объявлении одной из или обеих функций foo и boo:

http://coliru.stacked-crooked.com/a/2032ee3df28d3077

template<has_boo T>
requires(!has_foo<T>)
void func(const T& a) 
{
    a.boo();
}


Ну или на базе существующего создать новый концепт (концепты), расширенные и уточненные.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 25.11.2022 10:51 rg45 . Предыдущая версия .
Re: Ресолвинг неоднозначностей концептов
От: vopl Россия  
Дата: 25.11.22 12:52
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Привет, коллеги.


V>Сугубо из любопытства вопрос, есть ли возможность разресолвить неоднозначность в концептах тут:


Наверное можно сыграть на приоритетности more constrained, тут примеры про котов и самый последний https://en.cppreference.com/w/cpp/language/constraints
Re[2]: Ресолвинг неоднозначностей концептов
От: vopl Россия  
Дата: 25.11.22 13:40
Оценка: 10 (2)
Здравствуйте, vopl, Вы писали:

V>Здравствуйте, vdimas, Вы писали:


V>>Привет, коллеги.


V>>Сугубо из любопытства вопрос, есть ли возможность разресолвить неоднозначность в концептах тут:


V>Наверное можно сыграть на приоритетности more constrained, тут примеры про котов и самый последний https://en.cppreference.com/w/cpp/language/constraints


template<typename T>
concept has_foo = 
    requires(const T a) {
        a.foo();
    };

template<typename T>
concept has_boo = 
    requires(const T& a) {
        a.boo();
    };

template<typename T>
concept has_both = has_foo<T> && has_boo<T>;

template<has_foo T>
void func(const T& a)
{
    a.foo();
}

template<has_boo T>
void func(const T& a) {
    a.boo();
}

template<has_both T>
void func(const T& a) {
    a.foo();
    a.boo();
}

struct A {
    void foo() const {}
};

struct B {
    void boo() const {}
};

struct C {
    void foo() const {}
    void boo() const {}
};

void test() {
    A a;
    B b;
    C c;

    func(a);
    func(b);
    func(c);
}
Re[2]: Ресолвинг неоднозначностей концептов
От: vdimas Россия  
Дата: 25.11.22 15:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну, самое просто, наверное, это добавить дополнительный констрейнт в объявлении одной из или обеих функций foo и boo:

R>Ну или на базе существующего создать новый концепт (концепты), расширенные и уточненные.

Было любопытно уметь выбирать вариант ф-ии в месте использования, а не в месте объявления, т.к. такие ф-ии могут быть несвязанными, не знать друг о друге и тд.

Например, есть возможность выбрать желаемую сигнатуру ф-ии из набора перегрузок, указав приведение к сигнатуре.
Или можно явно указать параметры шаблонной ф-ии.

Чтобы можно было использовать где-то так:
void func(const has_foo auto & a) { 
    a.foo(); 
}

void func(const has_boo auto & a) { 
    a.boo(); 
}

...

func<has_foo auto>(c); // или просто func<has_foo>(c)
// или
((void(*)(has_foo auto &))func)(c);


Выше приведение к неполному типу, понятно, но в случае выбора ф-ии из мн-ва перегруженных их, компилятор де-факто не приводит значение адреса к требуемому типу, а выбирает ф-ию:
void f(int) {
    std::cout << "int" << std::endl;
}

void f(long) {
    std::cout << "long" << std::endl;
}

...

char c {};

f(c);
((void(*)(long))f)(c);
Отредактировано 25.11.2022 15:10 vdimas . Предыдущая версия . Еще …
Отредактировано 25.11.2022 15:10 vdimas . Предыдущая версия .
Отредактировано 25.11.2022 15:08 vdimas . Предыдущая версия .
Re[3]: Ресолвинг неоднозначностей концептов
От: rg45 СССР  
Дата: 25.11.22 15:56
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Было любопытно уметь выбирать вариант ф-ии в месте использования, а не в месте объявления, т.к. такие ф-ии могут быть несвязанными, не знать друг о друге и тд.


Думаю, прямо в месте использования вряд ли возможно. Приддется вокруг несвязанных функций делать объязку, устраняющую неоднозначности и потом пользоваться этой обвязкой, вместо прямого обращения к конфликтующим функциям.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 25.11.2022 16:34 rg45 . Предыдущая версия .
Re[4]: Ресолвинг неоднозначностей концептов
От: vdimas Россия  
Дата: 25.11.22 16:50
Оценка: :))
Здравствуйте, rg45, Вы писали:

R>Думаю, прямо в месте использования вряд ли возможно.


Ждём следующие версии языка. ))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.