3

在实现其构造函数采用的模板类时:

  1. 函数向量(函数的类型为std::function<bool(const T&)>
  2. std::binary_function<bool,bool,bool>我将使用它来将向量应用的结果从 1) 累积到某个值。

我希望能够使用std::plus()andstd::multiplies()作为第二个模板参数,但问题是根据函数我需要一个相应的中性元素(用于 std 累积初始值)。对于AND( std::multiplies) 我需要true(aka 1),对于OR( std::plus) 我需要false(aka 0)。我知道我可以专门化模板并解决问题,但我想知道是否有办法为内置的 STL 函数获取中性元素。

4

3 回答 3

6

如果您正在使用gcc,则可以使用__gnu_cxx::identity_element,这正是您所要求的。

如果你不是,我不认为有一个通用的解决方案,好像有,gcc不会实现他们自己的 - 你可能只是重写他们的实现(这实际上只是几个模板专业化,正如你所期望的那样)。

编辑:源代码在这个文件的第 78-98 行。

于 2012-10-17T09:13:54.770 回答
4

这里通常的解决方案是特征。与其实例化您的模板或其他任何东西,不如std::plus在一个特征类上实例化它,该类定义了一个typedeffor std::plus,加上一个标识元素(静态 const,带初始化器)以及您需要的任何其他东西。就像是:

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在需要时使用。

当然,在这两种情况下,您都必须提供所有必要的特征,无论是作为独立类还是作为模板特化。如果您需要的唯一两个标识元素是 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;
};

这在 C++11 之前不起作用,因为Op(1, 0)不是一个常量表达式。我不确定 C++11;但我认为如果 Op::operator()声明constexpr,它应该工作。(如果我必须涵盖很多运营商,包括客户可能提供的一些运营商,我只会费心尝试。)

于 2012-10-17T09:17:10.050 回答
3

只是从詹姆斯的回答(以及我对它的评论)中挑出一点。我认为应该分开考虑。

如果你愿意,你可以在运行时计算身份,假设确实有一个身份。是!func(true, false)

如果func::operator()可用并且没有副作用,就像std::plusand一样std::multiplies,那么大概任何明智的编译器都会在编译时实际计算它。但它在编译时不需要该值,所以现在您的模板可以(如果调用者想要)接受 astd::function<bool(bool,bool)>而不是需要在编译时知道实际的累积操作。

于 2012-10-17T09:32:50.227 回答