实现构造函数采用的模板类时:
std::function<bool(const T&)>
)std::binary_function<bool,bool,bool>
我将用于累积从1)到某个值的矢量应用结果。我希望能够使用std::plus()
和std::multiplies()
作为第二个模板参数,但问题是根据函数我需要一个相应的中性元素(对于std累积初始值)。对于AND
(std::multiplies
)我需要true
(又名1
),OR
(std::plus
)我需要false
(又名0
)。我知道我可以专门化模板并解决问题,但我想知道是否有办法为内置STL函数获取中性元素。
答案 0 :(得分:6)
如果您使用的是gcc
,则可以使用__gnu_cxx::identity_element,这正是您所要求的。
如果你不是,我认为没有一般的解决方案,好像有,gcc
不会实现自己的 - 你可能只是重写他们的实现(实际上只是一个一些模板专业化,如你所料)。
编辑:此代码的源代码位于this file的第78-98行。
答案 1 :(得分:4)
这里通常的解决方案是特质。而不是实例化你的
std::plus
上的模板或者其他什么,你可以在a上实例化它
traits类,为typedef
定义std::plus
,加上
identity元素(static const,with initializer),以及其他任何东西
需要。类似的东西:
struct OpTraitsAdd
{
typedef std::plus<int> Op;
static int const identity = 0;
};
struct OpTraitsMult
{
typedef std::multiplies<int> Op;
static int const identity = 1;
};
也可以从标准操作员那里获得特征, 使用显式专业化:
template <typename Op> struct OpTraits;
template<>
struct OpTraits<std::plus<int> >
{
static int const identity = 0;
};
template<>
struct OpTraits<std::multiplies<int> >
{
static int const identity = 1;
};
在这种情况下,您将通过运算符实例化您的类,并且
在需要时使用OpTraits<Op>::identity
。
在这两种情况下,当然,你必须提供所有必要的 traits,作为独立类或模板特化。 如果您需要的唯一两个标识元素是0和1,那么您可能是 能够通过以下方式自动完成:
template <bool idIs0> struct IdImpl;
template<>
struct IdImpl<false>
{
static int value = 1;
};
template<>
struct IdImpl<true>
{
static int value = 0;
};
template <typename Op>
struct Id
{
static int value = ItImpl<Op(1, 0) == 1>::value;
};
这将 not 在C ++ 11之前工作,因为Op(1, 0)
不是常数
epxression。我不确定C ++ 11;但我认为如果
Op::operator()
被声明为constexpr
,它应该有效。 (我只会
如果我不得不覆盖很多运营商,包括其中一些运营商,那就太费劲了
客户可能会提供。)
答案 2 :(得分:3)
从詹姆斯的答案(以及我对它的评论)中找出一点。我认为值得单独考虑。
如果您愿意,可以在运行时计算身份,假设确实存在身份。它是!func(true, false)
。
如果func::operator()
可用并且没有副作用,就像std::plus
和std::multiplies
一样,那么可能任何合理的编译器都会在编译时实际计算出来。但它在编译时不需要该值,因此现在您的模板可以(如果调用者想要的话)接受std::function<bool(bool,bool)>
而不需要在编译时知道实际的累积操作。