函子 operator() 的条件特化
Conditional specialization of functors operator()
我想请你帮忙解决我最近几天遇到的编程问题。让我试着解释一下我将要实现的...
我的目标是定义一组具有有效性的方程式。让我更详细地解释一下...
我考虑将每个方程式对象作为一个函子 - 定义 operator()
的 class。该运算符的定义应专门针对每种方程类型。专业化包含计算本身:
.h:
enum class IDs : int { A = 0, B = 1, C = 2 };
template<IDs WHICH>
struct Equation
{
int operator() ( void );
}
.cpp:
template<>
Equation<IDs::A>::operator()( void )
{
/* Just some sample equation */
return( 42 + 28 );
}
您可能已经注意到,专业化由枚举 class 成员 ID::?.
定义
这似乎有效。但我想添加所谓的可用性功能 - 该等式可能仅对某些用户对象类型有效。
There is 'validity group' declared:
/* Object types declaration */
namespace Objects {
using Object0 = boost::mpl::int_<0>;
using Object1 = boost::mpl::int_<1>;
using Object2 = boost::mpl::int_<2>;
}
/* Validity groups declaration */
using ValidityGroup1 = boost::mpl::vector<Object0, Object2>;
using ValidityGroup2 = boost::mpl::vector<Object1>;
我正在使用以下构造来启用或禁用 [=72=](使用 boost::enable_if)。只是为了展示我是如何使用它的:
template<typename TYPE_LIST, typename QUERY_TYPE>
struct IsTypeInList
{
using TypePos = typename boost::mpl::find<TYPE_LIST, QUERY_TYPE>::type;
using Finish = typename boost::mpl::end<TYPE_LIST>::type;
using type = typename boost::mpl::not_<boost::is_same<TypePos, Finish> >::type;
using value_type = typename type::value_type;
static const bool value = type::value;
};
template<typename OBJECT_TYPE, typename ENABLER=void>
class SampleClass;
template<typename OBJECT_TYPE>
class SampleClass<OBJECT_TYPE, typename boost::enable_if<typename IsTypeInList<ValidityGroup1, Object0>::type>::type>
{}
仅当 Object0
属于 ValidityGroup1
时,SampleClass 的偏特化才可用。到目前为止,一切都很好。这个原理得到了验证。
现在有趣的事情来了。我想将这两件事合并在一起:
目标:
Define Equation's operator() who's specialization containing valid body is defined by IDs::?? enum class value" 并且仅适用于属于 ValidityGroup 的对象...可以对相同的 IDs 进行另一个计算::?? 但对其他 ValidityGroup 中的对象有效(又名 Object0 的 属性 被计算Object1)
以外的其他方式
我知道整个概念很复杂,可能会造成混淆。让我展示一下我实现这些东西的尝试:
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID, typename ENABLER = void>
class Equation;
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
class Equation<OBJECT_TYPE, VALIDITY_GROUP, ID, typename boost::enable_if<typename IsTypeInList<VALIDITY_GROUP, OBJECT_TYPE>::type>::type >
: public EquationBase<IDs>
{
public:
int operator() ( void );
};
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
int Equation<OBJECT_TYPE, ValidityGroup1, Ids::A>::operator() ( void )
{
return( 42 + 56 );
}
但是 operator() 定义不起作用...您能告诉我如何使它起作用吗?或者有没有人有任何其他想法如何实现上面写的目标?
非常感谢任何愿意帮助我的人...
干杯马丁
编辑:
该等式用于模板 class 对象。让代码解释一下:
template<typename OBJECT_TYPE>
class Object
{
public:
Object( void );
};
.cpp:
template<typename OBJECT_TYPE>
Object<OBJECT_TYPE>::Object( void )
{
std::cout << Equation<IDs::A>()() << std::endl;
}
问题是 OBJECT_TYPE 在运算符 () 被专门化时未定义...
如果我没有理解错你想要得到什么,我想有很多方法。
以下是一个 iper 简化示例(但完整的广告工作),展示了如何 select 使用 std::enable_if
的不同实现(但 boost::enable_if
应该没问题)与 return 运算符类型
#include <iostream>
#include <type_traits>
template <typename ObjT, typename ValT>
class Equation
{
public:
template <typename X = ObjT>
typename std::enable_if<true == std::is_same<X, ValT>::value, int>::type
operator() ( void )
{ return( 0 ); }
template <typename X = ObjT>
typename std::enable_if<false == std::is_same<X, ValT>::value, int>::type
operator() ( void )
{ return( 1 ); }
};
int main()
{
Equation<int, int> eq0;
Equation<int, long> eq1;
std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
}
我想不是很优雅。
另一个解决方案(我想,最适合您的需求)可能是基于 class 部分专业化
#include <iostream>
#include <type_traits>
template <typename ObjT, typename ValT, bool = std::is_same<ObjT, ValT>::value>
class Equation;
template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, true>
{
public:
int operator() ();
};
template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, false>
{
public:
int operator() ();
};
template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, true>::operator() ()
{ return( 0 ); }
template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, false>::operator() ()
{ return( 1 ); }
int main()
{
Equation<int, int> eq0;
Equation<int, long> eq1;
std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
}
我想请你帮忙解决我最近几天遇到的编程问题。让我试着解释一下我将要实现的...
我的目标是定义一组具有有效性的方程式。让我更详细地解释一下...
我考虑将每个方程式对象作为一个函子 - 定义 operator()
的 class。该运算符的定义应专门针对每种方程类型。专业化包含计算本身:
.h:
enum class IDs : int { A = 0, B = 1, C = 2 };
template<IDs WHICH>
struct Equation
{
int operator() ( void );
}
.cpp:
template<>
Equation<IDs::A>::operator()( void )
{
/* Just some sample equation */
return( 42 + 28 );
}
您可能已经注意到,专业化由枚举 class 成员 ID::?.
定义这似乎有效。但我想添加所谓的可用性功能 - 该等式可能仅对某些用户对象类型有效。
There is 'validity group' declared:
/* Object types declaration */
namespace Objects {
using Object0 = boost::mpl::int_<0>;
using Object1 = boost::mpl::int_<1>;
using Object2 = boost::mpl::int_<2>;
}
/* Validity groups declaration */
using ValidityGroup1 = boost::mpl::vector<Object0, Object2>;
using ValidityGroup2 = boost::mpl::vector<Object1>;
我正在使用以下构造来启用或禁用 [=72=](使用 boost::enable_if)。只是为了展示我是如何使用它的:
template<typename TYPE_LIST, typename QUERY_TYPE>
struct IsTypeInList
{
using TypePos = typename boost::mpl::find<TYPE_LIST, QUERY_TYPE>::type;
using Finish = typename boost::mpl::end<TYPE_LIST>::type;
using type = typename boost::mpl::not_<boost::is_same<TypePos, Finish> >::type;
using value_type = typename type::value_type;
static const bool value = type::value;
};
template<typename OBJECT_TYPE, typename ENABLER=void>
class SampleClass;
template<typename OBJECT_TYPE>
class SampleClass<OBJECT_TYPE, typename boost::enable_if<typename IsTypeInList<ValidityGroup1, Object0>::type>::type>
{}
仅当 Object0
属于 ValidityGroup1
时,SampleClass 的偏特化才可用。到目前为止,一切都很好。这个原理得到了验证。
现在有趣的事情来了。我想将这两件事合并在一起:
目标:
Define Equation's operator() who's specialization containing valid body is defined by IDs::?? enum class value" 并且仅适用于属于 ValidityGroup 的对象...可以对相同的 IDs 进行另一个计算::?? 但对其他 ValidityGroup 中的对象有效(又名 Object0 的 属性 被计算Object1)
以外的其他方式我知道整个概念很复杂,可能会造成混淆。让我展示一下我实现这些东西的尝试:
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID, typename ENABLER = void>
class Equation;
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
class Equation<OBJECT_TYPE, VALIDITY_GROUP, ID, typename boost::enable_if<typename IsTypeInList<VALIDITY_GROUP, OBJECT_TYPE>::type>::type >
: public EquationBase<IDs>
{
public:
int operator() ( void );
};
template<typename OBJECT_TYPE, typename VALIDITY_GROUP, IDs ID>
int Equation<OBJECT_TYPE, ValidityGroup1, Ids::A>::operator() ( void )
{
return( 42 + 56 );
}
但是 operator() 定义不起作用...您能告诉我如何使它起作用吗?或者有没有人有任何其他想法如何实现上面写的目标?
非常感谢任何愿意帮助我的人...
干杯马丁
编辑: 该等式用于模板 class 对象。让代码解释一下:
template<typename OBJECT_TYPE>
class Object
{
public:
Object( void );
};
.cpp:
template<typename OBJECT_TYPE>
Object<OBJECT_TYPE>::Object( void )
{
std::cout << Equation<IDs::A>()() << std::endl;
}
问题是 OBJECT_TYPE 在运算符 () 被专门化时未定义...
如果我没有理解错你想要得到什么,我想有很多方法。
以下是一个 iper 简化示例(但完整的广告工作),展示了如何 select 使用 std::enable_if
的不同实现(但 boost::enable_if
应该没问题)与 return 运算符类型
#include <iostream>
#include <type_traits>
template <typename ObjT, typename ValT>
class Equation
{
public:
template <typename X = ObjT>
typename std::enable_if<true == std::is_same<X, ValT>::value, int>::type
operator() ( void )
{ return( 0 ); }
template <typename X = ObjT>
typename std::enable_if<false == std::is_same<X, ValT>::value, int>::type
operator() ( void )
{ return( 1 ); }
};
int main()
{
Equation<int, int> eq0;
Equation<int, long> eq1;
std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
}
我想不是很优雅。
另一个解决方案(我想,最适合您的需求)可能是基于 class 部分专业化
#include <iostream>
#include <type_traits>
template <typename ObjT, typename ValT, bool = std::is_same<ObjT, ValT>::value>
class Equation;
template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, true>
{
public:
int operator() ();
};
template <typename ObjT, typename ValT>
class Equation<ObjT, ValT, false>
{
public:
int operator() ();
};
template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, true>::operator() ()
{ return( 0 ); }
template <typename ObjT, typename ValT>
int Equation<ObjT, ValT, false>::operator() ()
{ return( 1 ); }
int main()
{
Equation<int, int> eq0;
Equation<int, long> eq1;
std::cout << "eq0 val: " << eq0() << std::endl; // print "eq0 val: 0"
std::cout << "eq1 val: " << eq1() << std::endl; // print "eq1 val: 1"
}