Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 26.09.15 08:52
Оценка:
Надо написать функцию, которая принимает любой параметр и передаёт его нужной перегрузке другой заранее известной функции.

Пример кода:

#include "stdio.h"

struct CR1
{
    CR1 () 
        { printf("CR1 ctor at %x\n", this); }
    ~CR1 ()                 
        { printf("CR1 dtor at %x\n", this); }
    CR1 (const CR1&)         
        { printf("CR1 copyctor at %x\n", this); }
    CR1& operator = (const CR1&) 
        { printf("CR1 = at %x\n", this); }
};

struct CR2
{
    CR2 () 
        { printf("CR2 ctor at %x\n", this); }
    ~CR2 ()                 
        { printf("CR2 dtor at %x\n", this); }
    CR2 (const CR2&)         
        { printf("CR2 copyctor at %x\n", this); }
    CR2& operator = (const CR2&) 
        { printf("CR2 = at %x\n", this); }
};

struct Base
{    
    Base (const CR1& cr) 
    { printf("const CR1&\n"); }

    Base (CR2& cr) 
    { printf("CR2&\n"); }
};

struct Derived : Base 
{
    template <typename Arg>
    Derived(const Arg& arg) : Base(arg) {} // что сюда писать?
};

int main ()
{    
    {
        CR1 cr;
        Derived der(cr);
    }

    getchar();

    return 0;
}

Допустим, Base переделывать нельзя. Надо, чтобы Derived жрал все конструкторы базы.
Конструктор Derived — типа универсальный передатчик. Но что-то не заладилось.

Сейчас у меня стоит const Arg& arg, и если я попробую передать в конструктор CR2 вместо CR1, то компилятор меня пошлёт, потому что константную ссылку переделать в неконстантную нельзя.

Если я напишу "универсальный конструктор" как Arg& arg, то будет проблема с попыткой передать в него временный объект.
warning C4239: nonstandard extension used : 'argument' : conversion from 'CR1' to 'CR1 &'


Если я напишу его как Arg arg, то проблем никаких не будет. Будет лишь лишнее копирование, что видно по выводу программы.


Написать два конструктора не предлагать, потому что у меня может быть 8 таких параметров.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re: Универсальная прокси-функция.
От: Vamp Россия  
Дата: 26.09.15 12:22
Оценка:
TB>Написать два конструктора не предлагать, потому что у меня может быть 8 таких параметров.

Именно для этого и были придуманы rvalue references. Google в помощь.
Да здравствует мыло душистое и веревка пушистая.
Re[2]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 26.09.15 12:52
Оценка:
Здравствуйте, Vamp, Вы писали:


TB>>Написать два конструктора не предлагать, потому что у меня может быть 8 таких параметров.


V>Именно для этого и были придуманы rvalue references. Google в помощь.


А средствами ++03?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Универсальная прокси-функция.
От: Vamp Россия  
Дата: 26.09.15 13:33
Оценка:
TB>>>Написать два конструктора не предлагать, потому что у меня может быть 8 таких параметров.

V>>Именно для этого и были придуманы rvalue references. Google в помощь.


TB>А средствами ++03?


Никак. Именно потому и придумали rvalue references, что без них никак.
Да здравствует мыло душистое и веревка пушистая.
Re[4]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 26.09.15 14:41
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Никак. Именно потому и придумали rvalue references, что без них никак.


Ну типа шаблон ProxyArg<T>::type определить, в нём определять, константен ли объект, и для константы делать const&, для неконстанты просто &.
Я просто на вывернутых шаблонах с хитрыми специализациями, сфинаями итд импровизировать не умею.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: Универсальная прокси-функция.
От: Vain Россия google.ru
Дата: 28.09.15 07:51
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Я просто на вывернутых шаблонах с хитрыми специализациями, сфинаями итд импровизировать не умею.

и не надо, оно нужно в << 1% случаев. если работодатель требует это как необходимость, предлагаю отфутболить его и выбрать другого более вменяемого.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Re[6]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 28.09.15 08:18
Оценка: -1
Здравствуйте, Vain, Вы писали:

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


TB>>Я просто на вывернутых шаблонах с хитрыми специализациями, сфинаями итд импровизировать не умею.

V>и не надо, оно нужно в << 1% случаев. если работодатель требует это как необходимость, предлагаю отфутболить его и выбрать другого более вменяемого.

Да и этот 1% не понадобился бы, если бы дохлый страус вовремя придумал рефлексию времени компиляции. Так сложно что ли добавить в язык constexpr-функцию "есть ли у такого класса такой метод с такой сигнатурой"?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[7]: Универсальная прокси-функция.
От: CEMb  
Дата: 29.09.15 06:31
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Да и этот 1% не понадобился бы, если бы дохлый страус вовремя придумал рефлексию времени компиляции. Так сложно что ли добавить в язык constexpr-функцию "есть ли у такого класса такой метод с такой сигнатурой"?


Ты постоянно пытаешься исправить проблемы своей кривой архитектуры за счёт введения непонятных вещей в язык, которые там кроме тебя никому не нужны. Не надо так
Re: Универсальная прокси-функция.
От: Zenden Россия  
Дата: 29.09.15 06:43
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Надо написать функцию, которая принимает любой параметр и передаёт его нужной перегрузке другой заранее известной функции.


TB>Сейчас у меня стоит const Arg& arg, и если я попробую передать в конструктор CR2 вместо CR1, то компилятор меня пошлёт, потому что константную ссылку переделать в неконстантную нельзя.


эээ

struct Derived : Base {
    template <typename Arg>
    Derived(const Arg& arg) : Base(const_cast<Arg&>(arg)) {} 
};
Re[8]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 29.09.15 07:11
Оценка: +1 :)
Здравствуйте, CEMb, Вы писали:

CEM>Ты постоянно пытаешься исправить проблемы своей кривой архитектуры за счёт введения непонятных вещей в язык, которые там кроме тебя никому не нужны. Не надо так


В 99% тем в профильном разделе можно зайти и не читая написать "скорее всего, у тебя неправильная архитектура, раз тебе это нужно". Поэтому я такие посты считаю дурным тоном.
Ну и рефлексию времени компиляции назвать "никому не нужной" — это уже запредельная дерзость.

Подожди, а может ты действительно написал пост, не читая?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 29.09.15 07:13
Оценка:
Здравствуйте, Zenden, Вы писали:

Z>эээ


Z>
Z>struct Derived : Base {
Z>    template <typename Arg>
Z>    Derived(const Arg& arg) : Base(const_cast<Arg&>(arg)) {} 
Z>};
Z>


Я имею в виду — нет нормального решения вопроса. К твоему коду нетрудно подобрать пример, который приведёт к неожиданностям.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Универсальная прокси-функция.
От: Кодт Россия  
Дата: 29.09.15 08:23
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Я имею в виду — нет нормального решения вопроса. К твоему коду нетрудно подобрать пример, который приведёт к неожиданностям.


Зависит от того, шашечки или ехать.

Если у тебя есть конкретная проблема с восемью сигнатурами конструкторов, для которой хочется придумать быстрое решение, — то, может быть, именно на твоём коде не будет неожиданностей.

А если ты хочешь найти решение "вообще", с придумыванием контрпримеров, — это другой разговор. (Вполне практический, если ты пишешь библиотеку для широкого использования). Но тут встаёт вопрос архитектуры

И кстати, если уж зашёл разговор о практических решениях, то пожалуйста, расскажи реальную задачу и покажи эскиз реального кода. А не переабстрагированного — CR1, CR2, Base, Derived — возможно, здесь ты с водой выплеснул ребёнка. Опять же, зачем морозить сигнатуры и зачем наследовать?
Перекуём баги на фичи!
Re[9]: offtop
От: CEMb  
Дата: 29.09.15 08:31
Оценка:
Здравствуйте, T4r4sB, Вы писали:

CEM>>Ты постоянно пытаешься исправить проблемы своей кривой архитектуры за счёт введения непонятных вещей в язык, которые там кроме тебя никому не нужны. Не надо так


TB>В 99% тем в профильном разделе можно зайти и не читая написать "скорее всего, у тебя неправильная архитектура, раз тебе это нужно". Поэтому я такие посты считаю дурным тоном.


Нет, нельзя. Твоя доработка сильно утяжелит внутреннюю структуру классов, кому это нужно, при условии, что не будет использоваться? Не, ты можешь пообщаться с авторами, предложить идею. Вот к примеру, архитектурное решение с виртуальными таблицами методов в классе существует, их можно включить и выключить. Если получится ровно так же, я не против.

TB>Ну и рефлексию времени компиляции назвать "никому не нужной" — это уже запредельная дерзость.


TB>Подожди, а может ты действительно написал пост, не читая?


Читал, и всё остальное, в том числе "почему в с++ нет проверки границ массива" тоже, потому и пишу.
Извини, конечно, но почему бы тебе не попробовать на Java писать? У Java более подходящая биосфера, там гибко можно использовать огромное количество библиотек, которые решают все проблемы.
Re[4]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 29.09.15 08:38
Оценка:
Здравствуйте, Кодт, Вы писали:

К>И кстати, если уж зашёл разговор о практических решениях, то пожалуйста, расскажи реальную задачу и покажи эскиз реального кода. А не переабстрагированного — CR1, CR2, Base, Derived — возможно, здесь ты с водой выплеснул ребёнка. Опять же, зачем морозить сигнатуры и зачем наследовать?


Очевидно, что тут имеется в виду тот же вопрос, который возникает при написании emplace_back или make_shared (только в ++03). Зачем притворяться, будто ты не понял, о чём речь?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[10]: offtop
От: T4r4sB Россия  
Дата: 29.09.15 08:40
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Нет, нельзя. Твоя доработка сильно утяжелит внутреннюю структуру классов, кому это нужно, при условии, что не будет использоваться? Не, ты можешь пообщаться с авторами, предложить идею. Вот к примеру, архитектурное решение с виртуальными таблицами методов в классе существует, их можно включить и выключить. Если получится ровно так же, я не против.


Чего-чего, внутренняя структура, виртуальные таблицы?
Я же написал: рефлексия времени компиляции.
Не, ты точно читаешь очень невнимательно, торопясь вставить очередную коронную фразу.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[11]: Универсальная прокси-функция.
От: CEMb  
Дата: 29.09.15 09:07
Оценка:
Здравствуйте, T4r4sB, Вы писали:

CEM>>Нет, нельзя. Твоя доработка сильно утяжелит внутреннюю структуру классов, кому это нужно, при условии, что не будет использоваться? Не, ты можешь пообщаться с авторами, предложить идею. Вот к примеру, архитектурное решение с виртуальными таблицами методов в классе существует, их можно включить и выключить. Если получится ровно так же, я не против.


TB>Чего-чего, внутренняя структура, виртуальные таблицы?

TB>Я же написал: рефлексия времени компиляции.
TB>Не, ты точно читаешь очень невнимательно, торопясь вставить очередную коронную фразу.

А, да, каюсь, я не прав про классы, это про время компиляции.

Проблема определения на момент компиляции наличия у класса метода с нужной сигнатурой решается, например, шаблонами.
class CGood
{
protected:
    void foo(const int& i){};
};
class CBad
{
protected:
    void foo(int& i){};
};

template<class T> class CT: public T
{
public:
    CT(const int& i);
};

template<class T> CT<T>::CT(const int& i)
{
    foo(i);
}

// once in code:

    CT<CGood> cg(1);    // OK
    CT<CBad> cb(1);    // Error
Re[12]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 29.09.15 09:17
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Проблема определения на момент компиляции наличия у класса метода с нужной сигнатурой решается, например, шаблонами.

...

CEM> CT<CGood> cg(1); // OK

CEM> CT<CBad> cb(1); // Error
CEM>[/ccode]

А теперь осталось это ОК/Еггог запихать в сфинью, чтобы получить HasMethod::value, и вся эта хренота вместо одной строки, которую уже десять лет просят добавить в язык.

Нагугленная же реализация примерно такая:
template <typename T>
    class HasSomeMethod
    {
        typedef char y;
        typedef y n[2];

        template <typename U, U> struct ReallyHas;
        template <typename C> static y& Test(ReallyHas <Result (C::*)(Args), &C::Method>*);
        template <typename> static n& Test(...);
    public:
    static bool const value = sizeof(Test<T>(0)) == sizeof(y);    
    };

Я до сих пор не понимаю, почему это надо делать именно так. Но когда я пробовал по-своему, по-другому, то у меня не получалось.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Отредактировано 29.09.2015 9:18 T4r4sB . Предыдущая версия .
Re[13]: Универсальная прокси-функция.
От: CEMb  
Дата: 29.09.15 09:49
Оценка:
Здравствуйте, T4r4sB, Вы писали:

CEM>>Проблема определения на момент компиляции наличия у класса метода с нужной сигнатурой решается, например, шаблонами.

TB>...

CEM>> CT<CGood> cg(1); // OK

CEM>> CT<CBad> cb(1); // Error
CEM>>[/ccode]

TB>А теперь осталось это ОК/Еггог запихать в сфинью, чтобы получить HasMethod::value, и вся эта хренота вместо одной строки, которую уже десять лет просят добавить в язык.


Интересная задачка
Напиши хотя бы псевдокодом, как ты себе это видишь?
Я пока вижу только условное ветвление в конструкторе, но компилятор всё равно ругнётся же на отсутствие метода, в обоих классах причём (в одном одного, в другом другого, как мне видится), поэтому хотелось бы увидеть псевдокод
Re[14]: Универсальная прокси-функция.
От: T4r4sB Россия  
Дата: 29.09.15 10:08
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Напиши хотя бы псевдокодом, как ты себе это видишь?


Да фиг знает, чёто такое, но это не сработает
template <typename T>
struct ToArg
{
    static if IsConst(T)
    {
         typedef const T& type;
    } else
    {
        typedef T& type;
    }
};

// ...
template <typename A1>
Derived (ToArg<A1>::type a1) : Base(a1) {}


А в идеале так:
static for (int i=0; i<static_reflexion<Base>::constructors::size; ++i)
{
    Derived(static_reflexion<Base>::constructors[i]::Args... args) : Base(args...) {}
}
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[5]: Универсальная прокси-функция.
От: Кодт Россия  
Дата: 29.09.15 14:27
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Очевидно, что тут имеется в виду тот же вопрос, который возникает при написании emplace_back или make_shared (только в ++03). Зачем притворяться, будто ты не понял, о чём речь?


Не разглядел emplace_back и make_shared в исходном сообщении. Старею?
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.