Я создал класс either<l, r>
очень похожий на Either a b
в Haskell. Я также реализовал функцию map
прямо в классе; вот как выглядит код:
template<typename l, typename r>
class either
{
template<typename b>
either<l, b> map(const std::function<b (r)> &f)
{
// ...
}
};
Теперь я хочу изолировать функцию map
, чтобы создать абстрактный базовый класс с именем functor
.
template<typename a, template <a> class derived>
class functor
{
public:
virtual ~functor();
template<typename b>
derived<b> map(const std::function<b (a)> &f) = nullptr;
};
either
унаследует этот класс:
class either : functor<r, either<l, r>>
однако это недопустимый C++, поскольку функции-члены шаблона не могут быть виртуальными.
Более того, я попытался проверить, может ли <r, either<l, r>>
соответствовать <a, derived<a>>
в functor<r, either<l, r>>
(или любому другому шаблону в этом отношении), но не смог, поскольку у него есть два параметра шаблона. Также обратите внимание, что другие производные классы функтора могут иметь другое количество аргументов шаблона, которые не имеют отношения к функтору.
Можно ли выразить базовый класс функтора в шаблонах C++?
virtual
. Это ничего не даст в вашем случае использования наследования, если вы не добавите возможность внедрить класс для наследования через параметр шаблона, и в этот момент вам не понадобится виртуальный. - person pmr   schedule 22.07.2014template<typename a, typename b, typename C> typename C::rebind<b>::other map(const std::function<b (a)> &f, const C& c);
- person Jarod42   schedule 22.07.2014functor::map
виртуальным. Как именно вы планируете его использовать таким образом, который требует полиморфизма? Как, по-вашему, будет выглядеть место для звонков? - person Igor Tandetnik   schedule 22.07.2014D<float> instance
) и производную отfunctor<float, D<float>>
. Теперь возьмем функциюstd::function<int (float)> discretize
. Я хочу, чтобы моя структура данных могла превратиться из D‹float› в D‹int›, написавinstance.map(discretize);
. Здесь компилятор должен сделать вывод, чтоb
в объявленииmap
являетсяint
, и он должен искать определения функцииD<float>.map<int>(const std::function<int (float)> &)
в производном классе. - person Maarten   schedule 22.07.2014map
был виртуальным. Вы не вызываетеmap
через указатель или ссылку наfunctor
. Я вообще не понимаю, зачем вамfunctor
. - person Igor Tandetnik   schedule 22.07.2014template<typename <float> DS> DS<int> discretizeAny(DS<float> &ds) { return ds.map(discretize); }
, которая дискретизирует любую структуру данных, являющуюся функтором, будь тоD
,list
,tree
и так далее? Я не спрашиваю, зачем мне нужен функтор, я спрашиваю, возможно ли определить класс на C++, который гарантирует, что все неабстрактные производные классы могут быть отображены. - person Maarten   schedule 22.07.2014DS
, а неfunctor
. Каково предполагаемое определениеDS
? - person Igor Tandetnik   schedule 22.07.2014functor
, когдаdiscretizeAny
не упоминает и не используетfunctor
ни в какой форме?discretizeAny
будет вполне успешно работать с любым классом, имеющим функцию-член с именемmap
, виртуальную или иную, с подходящей подписью. См. также утиный ввод - person Igor Tandetnik   schedule 22.07.2014map
с совместимой сигнатурой типа. Пожалуйста, обратите внимание, что я задаю вопрос из искреннего интереса к языку программирования C++, а не потому, что у меня крайний срок разработки программного обеспечения. - person Maarten   schedule 22.07.2014functor
обеспечивает более надежную гарантию, чем функция-член с именемmap
. Какие дополнительные гарантии вы хотели бы иметь и почему? - person Igor Tandetnik   schedule 22.07.2014map id = id
иmap (p . q) = (map p) . (map q)
. Конечно, нереально проверить, соблюдаются ли эти законы для производного класса в таком языке программирования, как C++, поэтому давайте пока проигнорируем это. Из-за ошибки программиста возможно, что не-функтор (у которого просто есть карта функций) передается функции, которая опирается на законы функтора. Строго типизированная система предупредит во время компиляции, что передаваемый объект не является производным от функтора. Утиная печать не уловила бы такую ошибку программирования. - person Maarten   schedule 22.07.2014id
и.
. В любом случае, производное отfunctor
, по-видимому, ничего из этого не гарантирует. Я также не уверен, что вы подразумеваете под нефунктором (у которого просто есть функцияmap
). Класс, у которого есть функцияmap
с подходящей сигнатурой, звучит для меня как функтор. - person Igor Tandetnik   schedule 22.07.2014struct functor{};
, выведите свои классы изfunctor
и вdiscretizeAll
напишитеstatic_assert(is_base_of<functor, decltype(ds)>::value, "must derive from functor");
- person Igor Tandetnik   schedule 22.07.2014template<class T> struct is_map_functor: std::false_type {}; template<> struct is_map_functor<discretizeAny>: std::true_type {};
См. также:std::is_fundamental
иstd::is_integral
и тысячи им подобных. cplusplus.com/reference/type_traits/is_fundamental - person Mooing Duck   schedule 22.07.2014