You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
469 lines
11 KiB
C++
469 lines
11 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkDispatcher.h
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// The Loki Library
|
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
|
// This code accompanies the book:
|
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
|
// Permission to use, copy, modify, distribute and sell this software for any
|
|
// purpose is hereby granted without fee, provided that the above copyright
|
|
// notice appear in all copies and that both that copyright notice and this
|
|
// permission notice appear in supporting documentation.
|
|
// The author or Addison-Wesley Longman make no representations about the
|
|
// suitability of this software for any purpose. It is provided "as is"
|
|
// without express or implied warranty.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#ifndef vtkDispatcher_Private_h
|
|
#define vtkDispatcher_Private_h
|
|
|
|
#include "vtkConfigure.h"
|
|
|
|
#ifndef VTK_LEGACY_REMOVE
|
|
#ifndef __VTK_WRAP__
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <typeinfo>
|
|
|
|
namespace vtkDispatcherPrivate
|
|
{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Dispatch helper for reference functors
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class BaseLhs, class SomeLhs, typename RT, class CastLhs, class Fun>
|
|
class FunctorRefDispatcherHelper
|
|
{
|
|
Fun& fun_;
|
|
|
|
public:
|
|
typedef RT ResultType;
|
|
|
|
FunctorRefDispatcherHelper(const FunctorRefDispatcherHelper& rhs)
|
|
: fun_(rhs.fun_)
|
|
{
|
|
}
|
|
FunctorRefDispatcherHelper(Fun& f)
|
|
: fun_(f)
|
|
{
|
|
}
|
|
|
|
ResultType operator()(BaseLhs& lhs) { return fun_(CastLhs::Cast(lhs)); }
|
|
|
|
private:
|
|
FunctorRefDispatcherHelper& operator=(const FunctorRefDispatcherHelper& b);
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Dispatch helper
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class BaseLhs, class SomeLhs, typename RT, class CastLhs, class Fun>
|
|
class FunctorDispatcherHelper
|
|
{
|
|
Fun fun_;
|
|
|
|
public:
|
|
typedef RT ResultType;
|
|
|
|
FunctorDispatcherHelper(const FunctorDispatcherHelper& rhs)
|
|
: fun_(rhs.fun_)
|
|
{
|
|
}
|
|
FunctorDispatcherHelper(Fun fun)
|
|
: fun_(fun)
|
|
{
|
|
}
|
|
|
|
ResultType operator()(BaseLhs& lhs) { return fun_(CastLhs::Cast(lhs)); }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Parent class for all FunctorImpl, helps hide functor template args
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <typename R, typename P1>
|
|
class FunctorImpl
|
|
{
|
|
public:
|
|
typedef R ResultType;
|
|
typedef P1 Parm1;
|
|
|
|
virtual ~FunctorImpl() {}
|
|
virtual R operator()(P1&) = 0;
|
|
virtual FunctorImpl* DoClone() const = 0;
|
|
|
|
template <class U>
|
|
static U* Clone(U* pObj)
|
|
{
|
|
if (!pObj)
|
|
return nullptr;
|
|
U* pClone = static_cast<U*>(pObj->DoClone());
|
|
assert(typeid(*pClone) == typeid(*pObj));
|
|
return pClone;
|
|
}
|
|
|
|
protected:
|
|
FunctorImpl() {}
|
|
FunctorImpl(const FunctorImpl&) {}
|
|
|
|
private:
|
|
FunctorImpl& operator=(const FunctorImpl&) = delete;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Impl functor that calls a user functor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class ParentFunctor, typename Fun>
|
|
class FunctorHandler : public ParentFunctor::Impl
|
|
{
|
|
typedef typename ParentFunctor::Impl Base;
|
|
|
|
public:
|
|
typedef typename Base::ResultType ResultType;
|
|
typedef typename Base::Parm1 Parm1;
|
|
|
|
FunctorHandler(Fun& fun)
|
|
: f_(fun)
|
|
{
|
|
}
|
|
~FunctorHandler() override {}
|
|
|
|
ResultType operator()(Parm1& p1) override { return f_(p1); }
|
|
FunctorHandler* DoClone() const override { return new FunctorHandler(*this); }
|
|
|
|
private:
|
|
Fun f_;
|
|
FunctorHandler(const FunctorHandler& b)
|
|
: ParentFunctor::Impl(b)
|
|
, f_(b.f_)
|
|
{
|
|
}
|
|
FunctorHandler& operator=(const FunctorHandler& b) = delete;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Functor wrapper class
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <typename R, typename Parm1>
|
|
class Functor
|
|
{
|
|
public:
|
|
typedef FunctorImpl<R, Parm1> Impl;
|
|
typedef R ResultType;
|
|
|
|
Functor()
|
|
: spImpl_()
|
|
{
|
|
}
|
|
|
|
Functor(const Functor& rhs)
|
|
: spImpl_(Impl::Clone(rhs.spImpl_.get()))
|
|
{
|
|
}
|
|
|
|
template <typename Fun>
|
|
Functor(Fun fun)
|
|
: spImpl_(new FunctorHandler<Functor, Fun>(fun))
|
|
{
|
|
}
|
|
|
|
Functor& operator=(const Functor& rhs)
|
|
{
|
|
Functor copy(rhs);
|
|
spImpl_.swap(copy.spImpl_);
|
|
return *this;
|
|
}
|
|
|
|
ResultType operator()(Parm1& p1) { return (*spImpl_)(p1); }
|
|
|
|
private:
|
|
std::unique_ptr<Impl> spImpl_;
|
|
};
|
|
|
|
}
|
|
|
|
namespace vtkDoubleDispatcherPrivate
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Dispatch helper
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, typename RT, class CastLhs,
|
|
class CastRhs, class Fun>
|
|
class FunctorRefDispatcherHelper
|
|
{
|
|
Fun& fun_;
|
|
|
|
public:
|
|
typedef RT ResultType;
|
|
FunctorRefDispatcherHelper(const FunctorRefDispatcherHelper& rhs)
|
|
: fun_(rhs.fun_)
|
|
{
|
|
}
|
|
FunctorRefDispatcherHelper(Fun& fun)
|
|
: fun_(fun)
|
|
{
|
|
}
|
|
|
|
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
|
|
{
|
|
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
|
}
|
|
|
|
private:
|
|
FunctorRefDispatcherHelper& operator=(const FunctorRefDispatcherHelper& b);
|
|
};
|
|
|
|
template <class BaseLhs, class BaseRhs, class SomeLhs, class SomeRhs, typename RT, class CastLhs,
|
|
class CastRhs, class Fun>
|
|
class FunctorDoubleDispatcherHelper
|
|
{
|
|
Fun fun_;
|
|
|
|
public:
|
|
typedef RT ResultType;
|
|
FunctorDoubleDispatcherHelper(const FunctorDoubleDispatcherHelper& rhs)
|
|
: fun_(rhs.fun_)
|
|
{
|
|
}
|
|
FunctorDoubleDispatcherHelper(Fun fun)
|
|
: fun_(fun)
|
|
{
|
|
}
|
|
|
|
ResultType operator()(BaseLhs& lhs, BaseRhs& rhs)
|
|
{
|
|
return fun_(CastLhs::Cast(lhs), CastRhs::Cast(rhs));
|
|
}
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Parent class for all FunctorImpl, helps hide functor template args
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <typename R, typename P1, typename P2>
|
|
class FunctorImpl
|
|
{
|
|
public:
|
|
typedef R ResultType;
|
|
typedef P1 Parm1;
|
|
typedef P2 Parm2;
|
|
|
|
virtual ~FunctorImpl() {}
|
|
virtual R operator()(P1&, P2&) = 0;
|
|
virtual FunctorImpl* DoClone() const = 0;
|
|
|
|
template <class U>
|
|
static U* Clone(U* pObj)
|
|
{
|
|
if (!pObj)
|
|
return nullptr;
|
|
U* pClone = static_cast<U*>(pObj->DoClone());
|
|
assert(typeid(*pClone) == typeid(*pObj));
|
|
return pClone;
|
|
}
|
|
|
|
protected:
|
|
FunctorImpl() {}
|
|
FunctorImpl(const FunctorImpl&) {}
|
|
|
|
private:
|
|
FunctorImpl& operator=(const FunctorImpl&) = delete;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Impl functor that calls a user functor
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class ParentFunctor, typename Fun>
|
|
class FunctorHandler : public ParentFunctor::Impl
|
|
{
|
|
typedef typename ParentFunctor::Impl Base;
|
|
|
|
public:
|
|
typedef typename Base::ResultType ResultType;
|
|
typedef typename Base::Parm1 Parm1;
|
|
typedef typename Base::Parm2 Parm2;
|
|
|
|
FunctorHandler(const Fun& fun)
|
|
: f_(fun)
|
|
{
|
|
}
|
|
~FunctorHandler() override {}
|
|
|
|
ResultType operator()(Parm1& p1, Parm2& p2) override { return f_(p1, p2); }
|
|
|
|
FunctorHandler* DoClone() const override { return new FunctorHandler(*this); }
|
|
|
|
private:
|
|
Fun f_;
|
|
FunctorHandler(const FunctorHandler& b)
|
|
: ParentFunctor::Impl(b)
|
|
, f_(b.f_)
|
|
{
|
|
}
|
|
FunctorHandler& operator=(const FunctorHandler& b) = delete;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Functor wrapper class
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <typename R, typename Parm1, typename Parm2>
|
|
class Functor
|
|
{
|
|
public:
|
|
typedef FunctorImpl<R, Parm1, Parm2> Impl;
|
|
typedef R ResultType;
|
|
|
|
Functor()
|
|
: spImpl_()
|
|
{
|
|
}
|
|
|
|
Functor(const Functor& rhs)
|
|
: spImpl_(Impl::Clone(rhs.spImpl_.get()))
|
|
{
|
|
}
|
|
|
|
template <typename Fun>
|
|
Functor(const Fun& fun)
|
|
: spImpl_(new FunctorHandler<Functor, Fun>(fun))
|
|
{
|
|
}
|
|
|
|
Functor& operator=(const Functor& rhs)
|
|
{
|
|
Functor copy(rhs);
|
|
spImpl_.swap(copy.spImpl_);
|
|
return *this;
|
|
}
|
|
|
|
ResultType operator()(Parm1& p1, Parm2& p2) { return (*spImpl_)(p1, p2); }
|
|
|
|
private:
|
|
std::unique_ptr<Impl> spImpl_;
|
|
};
|
|
}
|
|
|
|
namespace vtkDispatcherCommon
|
|
{
|
|
|
|
template <class To, class From>
|
|
struct DynamicCaster
|
|
{
|
|
static To& Cast(From& obj) { return dynamic_cast<To&>(obj); }
|
|
|
|
static To* Cast(From* obj) { return dynamic_cast<To*>(obj); }
|
|
};
|
|
|
|
template <class To, class From>
|
|
struct vtkCaster
|
|
{
|
|
static To& Cast(From& obj) { return *(To::SafeDownCast(&obj)); }
|
|
|
|
static To* Cast(From* obj) { return To::SafeDownCast(obj); }
|
|
};
|
|
|
|
class TypeInfo
|
|
{
|
|
public:
|
|
// Constructors
|
|
TypeInfo(); // needed for containers
|
|
TypeInfo(const std::type_info&); // non-explicit
|
|
|
|
// Access for the wrapped std::type_info
|
|
const std::type_info& Get() const;
|
|
// Compatibility functions
|
|
bool before(const TypeInfo& rhs) const;
|
|
const char* name() const;
|
|
|
|
private:
|
|
const std::type_info* pInfo_;
|
|
};
|
|
|
|
// Implementation
|
|
|
|
inline TypeInfo::TypeInfo()
|
|
{
|
|
class Nil
|
|
{
|
|
};
|
|
pInfo_ = &typeid(Nil);
|
|
assert(pInfo_);
|
|
}
|
|
|
|
inline TypeInfo::TypeInfo(const std::type_info& ti)
|
|
: pInfo_(&ti)
|
|
{
|
|
assert(pInfo_);
|
|
}
|
|
|
|
inline bool TypeInfo::before(const TypeInfo& rhs) const
|
|
{
|
|
assert(pInfo_);
|
|
// type_info::before return type is int in some VC libraries
|
|
return pInfo_->before(*rhs.pInfo_) != 0;
|
|
}
|
|
|
|
inline const std::type_info& TypeInfo::Get() const
|
|
{
|
|
assert(pInfo_);
|
|
return *pInfo_;
|
|
}
|
|
|
|
inline const char* TypeInfo::name() const
|
|
{
|
|
assert(pInfo_);
|
|
return pInfo_->name();
|
|
}
|
|
|
|
// Comparison operators
|
|
|
|
inline bool operator==(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
// type_info::operator== return type is int in some VC libraries
|
|
{
|
|
return (lhs.Get() == rhs.Get()) != 0;
|
|
}
|
|
|
|
inline bool operator<(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
{
|
|
return lhs.before(rhs);
|
|
}
|
|
|
|
inline bool operator!=(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
{
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
inline bool operator>(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
{
|
|
return rhs < lhs;
|
|
}
|
|
|
|
inline bool operator<=(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
{
|
|
return !(lhs > rhs);
|
|
}
|
|
|
|
inline bool operator>=(const TypeInfo& lhs, const TypeInfo& rhs)
|
|
{
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
}
|
|
|
|
#endif // wrapping
|
|
#endif // legacy remove
|
|
#endif // vtkDispatcherPrivate_h
|
|
// VTK-HeaderTest-Exclude: vtkDispatcher_Private.h
|