我试图处理只与以下某些组合兼容的图像处理操作类:
一种工作方法是定义一个通用模板类来处理默认情况(即:什么都不做),如下所示:
template <int dimension, typename dataType>
class IPOperation
{
public:
void execute()
{
std::cout << "do nothing" << std::endl;
}
};
然后我必须为所有支持的类型组合编写该类的特化,例如:
template<>
class IPOperation<2,float>
{
public:
void execute()
{
std::cout << "do something" << std::endl;
}
};
但是由于支持的维度/类型组合的数量可能变得非常大,这种方法总是有点过分。
受策略驱动设计的启发,为模板类配备特定限制会更好,如下所示:
template <int dimension, typename dataType>
class IPOperation : public supportedDimensions<2,3,4>, public supportedTypes<int, float, double>
{
void execute()
{
std::cout << "execute()" << std::endl;
}
};
到目前为止,我的糟糕做法是这样(而且看起来非常糟糕,我无法帮助自己):
#include <iostream>
#include <vector>
template <int... supportedDimensions>
class IPDimensions
{
private:
public:
static std::vector<int> getSupportedDimensions()
{
return { supportedDimensions... };
}
static bool supportsDimension(int dim)
{
std::vector<int> dimensions = getSupportedDimensions();
return std::find(dimensions.begin(), dimensions.end(), dim) != dimensions.end();
}
};
template <int dim>
class IPOperation : public IPDimensions<2,3>
{
private:
public:
void execute(void)
{
if(IPOperation::supportsDimension(dim))
{
std::cout << dim << "d is supported -> execute" << std::endl;
}
else
{
std::cout << dim << "d is not supported -> sit down and do nothing" << std::endl;
}
}
};
int main(int argc, const char * argv[])
{
IPOperation<2>* okay = new IPOperation<2>();
IPOperation<4>* notOkay = new IPOperation<4>();
okay->execute();
notOkay->execute();
}
当尝试将类似的东西应用于类型时,我完全迷失了。如果您使用策略作为特定策略的委托,那么使用某种机制来进行某些检查会很不错。也许我的方法是错误的方式,这整个事情可以通过宏,枚举或特征和std :: enable_if更简单地实现,使函数仅对定义的场景可见,但因为我花了一些时间阅读一些c ++ 11主题,我真的不确定任何事情了。
先谢谢你们提出任何有用的建议!
答案 0 :(得分:1)
我使用SFINAE来解决这类问题,例如:
template<std::size_t dimensions, typename dataType, typename=void> class IPOperation;
template<std::size_t dimensions, typename dataType>
class IPOperation<dimensions, dataType,
std::enable_if<(0<dimensions && dimensions<4) &&
std::is_floatingpoint<dataType>::value >::type>
{
/* ... */
};
IPOperation<2,float> a; // okay
IPOperation<4,float> b; // compile-time error: wrong dimensionality
IPOperation<3,int> c; // compile-time error: wrong dataType
或static_assert
:
template<std::size_t dimensions, typename dataType>
class IPOperation<dimensions, dataType>
{
static_assert(0<dimensions && dimensions<4,"wrong dimension");
static_assert(std::is_floatingpoint<dataType>::value,"incompatible data type");
/* ... */
};
它提供了更好的错误消息。
答案 1 :(得分:1)
如果要为不支持的类型允许虚拟操作(但没有编译错误),可以使用类似下面的内容:
#include <type_traits>
#include <iostream>
template <class...>
struct supportedTypes {
template <class X>
static constexpr bool check() { return false; };
};
template <class A, class... R>
struct supportedTypes<A, R...> {
template <class X>
static constexpr bool check() {
return std::is_same<X, A>::value
|| supportedTypes<R...>::template check<X>(); }
};
int main() {
std::cout << supportedTypes<int,double>::check<int>();
std::cout << supportedTypes<int,double>::check<void>();
}
答案 2 :(得分:0)
您可以利用boost::mpl::set
检查是否支持给定的维度/类型。如果要在编译时拒绝不支持的类型,请使用static_assert
;如果您确实需要“默认情况下不执行任何操作”逻辑,请使用SFINAE。
#include <iostream>
#include <boost/mpl/set.hpp>
#include <boost/mpl/set_c.hpp>
using namespace boost::mpl;
template <std::size_t Dim, typename Type>
struct Op {
static_assert(has_key<set_c<std::size_t, 2, 3, 4>,
integral_c<std::size_t, Dim>>::value,
"Unsupported dimension!");
static_assert(has_key<set<int, float, double>, Type>::value,
"Unsupported type!");
void Execute() {
std::cout << "DoSomething" << std::endl;
}
};
int main() {
// Op<1, int> x; // error: Unsupported dimension!
// Op<2, std::string> x; // error: Unsupported type!
Op<2, int> x;
x.Execute();
}
打印:
DoSomething
#include <iostream>
#include <boost/mpl/set.hpp>
#include <boost/mpl/set_c.hpp>
using namespace boost::mpl;
template <std::size_t Dim, typename Type, typename = void>
struct Op {
void Execute() {
std::cout << "DoNothing" << std::endl;
}
};
template <std::size_t Dim, typename Type>
struct Op<Dim,
Type,
std::enable_if_t<has_key<set_c<std::size_t, 2, 3, 4>,
integral_c<std::size_t, Dim>>::value &&
has_key<set<int, float, double>, Type>::value>> {
void Execute() {
std::cout << "DoSomething" << std::endl;
}
};
int main() {
Op<1, int> x;
Op<2, int> y;
x.Execute();
y.Execute();
}
打印:
DoNothing
DoSomething