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++

/*=========================================================================
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