blob: 464e8bafcea8cd7309c0e0eb9210bb55d405828b [file] [log] [blame]
/** @file
Meta programming support for WCCP.
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#pragma once
#include <algorithm>
// Various meta programming efforts. Experimental at present.
namespace ts
{
// Some support templates so we can fail to compile if the
// compile time check fails.
// This creates the actual error, depending on whether X has a valid
// nest type Result.
template <typename X> struct TEST_RESULT {
typedef typename X::Result type;
};
// Bool checking - a base template then specializations to succeed or
// fail.
template <bool VALUE> struct TEST_BOOL {
};
// Successful test defines Result.
template <> struct TEST_BOOL<true> {
typedef int Result;
};
// Failing test does not define Result.
template <> struct TEST_BOOL<false> {
};
// Fail to compile if VALUE is not true.
template <bool VALUE> struct TEST_IF_TRUE : public TEST_RESULT<TEST_BOOL<VALUE>> {
};
// Helper for assigning a value to all instances in a container.
template <typename T, typename R, typename A1> struct TsAssignMember : public std::binary_function<T, A1, R> {
R T::*_m;
A1 _arg1;
TsAssignMember(R T::*m, A1 const &arg1) : _m(m), _arg1(arg1) {}
R
operator()(T &t) const
{
return t.*_m = _arg1;
}
};
// Helper function to compute types for TsAssignMember.
template <typename T, typename R, typename A1>
struct TsAssignMember<T, R, A1>
assign_member(R T::*m, A1 const &arg1) {
return TsAssignMember<T, R, A1>(m, arg1);
}
// Overload for_each to operate on a container.
template <typename C, typename F>
void
for_each(C &c, F const &f)
{
std::for_each(c.begin(), c.end(), f);
}
/** Calc minimal value over a direct type container.
This handles an accessor that takes a argument.
*/
template <typename C, typename V, typename ARG1>
V
minima(C const &c, V (C::value_type::*ex)(ARG1) const, ARG1 const &arg1)
{
V v = std::numeric_limits<V>::max();
for (typename C::const_iterator spot = c.begin(), limit = c.end(); spot != limit; ++spot) {
v = std::min(v, ((*spot).*ex)(arg1));
}
return v;
}
/** Calc minimal value over a paired type container.
This handles an accessor that takes a argument.
*/
template <typename C, typename V, typename ARG1>
V
minima(C const &c, V (C::value_type::second_type::*ex)(ARG1) const, ARG1 const &arg1)
{
V v = std::numeric_limits<V>::max();
for (typename C::const_iterator spot = c.begin(), limit = c.end(); spot != limit; ++spot) {
v = std::min(v, ((spot->second).*ex)(arg1));
}
return v;
}
/** Apply a unary method to every object in a direct container.
*/
template <typename C, typename V, typename ARG1>
void
for_each(C &c, V (C::value_type::*ex)(ARG1), ARG1 const &arg1)
{
for (typename C::iterator spot = c.begin(), limit = c.end(); spot != limit; ++spot)
((*spot).*ex)(arg1);
}
/** Apply a unary method to every object in a paired container.
*/
template <typename C, typename V, typename ARG1>
void
for_each(C &c, V (C::value_type::second_type::*ex)(ARG1) const, ARG1 const &arg1)
{
for (typename C::iterator spot = c.begin(), limit = c.end(); spot != limit; ++spot)
((spot->second).*ex)(arg1);
}
template <typename Elt, ///< Element type.
typename Value ///< Member value type.
>
struct MemberPredicate {
Value const &m_value; ///< Value to test against.
Value Elt::*m_mptr; ///< Pointer to member to test.
MemberPredicate(Value Elt::*mptr, Value const &v) : m_value(v), m_mptr(mptr) {}
bool
operator()(Elt const &elt) const
{
return elt.*m_mptr == m_value;
}
};
template <typename T, typename V>
MemberPredicate<T, V>
predicate(V T::*m, V const &v)
{
return MemberPredicate<T, V>(m, v);
}
template <typename Elt, ///< Element type.
typename Value ///< Member value type.
>
struct MethodPredicate {
typedef Value (Elt::*MethodPtr)() const;
Value const &m_value; ///< Value to test against.
MethodPtr m_mptr; ///< Pointer to method returning value.
MethodPredicate(MethodPtr mptr, Value const &v) : m_value(v), m_mptr(mptr) {}
bool
operator()(Elt const &elt) const
{
return (elt.*m_mptr)() == m_value;
}
};
template <typename T, typename V>
MethodPredicate<T, V>
predicate(V (T::*m)() const, V const &v)
{
return MethodPredicate<T, V>(m, v);
}
} // namespace ts