std::integral_constant 背后的原因是什么?

What's the reason behind having std::integral_constant?

这个的真正用例是什么?

std::integral_constant

我可以理解这是一个值为 2 的包装器:

typedef std::integral_constant<int, 2> two_t

但为什么不直接使用 2 或用 2 定义一个 const int 值呢?

2 是值,而 two_t 是类型。它们是两种不同的抽象。每个都有其目的。

  • 您不能在需要类型的地方使用 2
  • 您不能在需要整数值的地方使用 two_t

更重要的是,std::true_typestd::false_typestd::integral_constant使用最广泛的特化。它们广泛用于 type_traits

在某些情况下 std::integral_constant 非常有用。

其中之一是标签分发。例如,std::true_typestd::false_type 分别只是 std::integral_constant<bool, true>std::integral_constant<bool, false>。每个 type trait 派生自 std::true_typestd::false_type,这会启用标签分发:

template <typename T>
int foo_impl(T value, std::true_type) {
    // Implementation for arithmetic values
}

template <typename T>
double foo_impl(T value, std::false_type) {
    // Implementation for non-arithmetic values
}

template <typename T>
auto foo(T value) {
    // Calls the correct implementation function, which return different types.
    // foo's return type is `int` if it calls the `std::true_type` overload
    // and `double` if it calls the `std::false_type` overload
    return foo_impl(value, std::is_arithmetic<T>{});
}

此外,模板元编程库通常只有类型列表的算法,而不是值列表。如果您想改为使用这些算法来获取值,则必须使用 std::integral_constant

之类的东西

下面的代码片段是我使用 std::integral_constant 创建一个 api 的一种方法,它采用通用值,但它还会在编译时检查您提供的值是否有效。

#include<iostream>

struct Value {};
struct Color {};
struct Size {};
struct Point {};

enum class Property {
    Color,
    StrokeColor,
    Opacity,
    Size,
    Position,
};

class Dom {
public:
    // give a single api to setValue
    template<Property prop, typename AnyValue>
    void setValue(const std::string &obj, AnyValue value){
        setValue(std::integral_constant<Property, prop>{}, obj, value);
    }
private:
    // specialization for each property and value type pair.
    void setValue(std::integral_constant<Property, Property::Color> type,
                  const std::string &obj,
                  Color col) {std::cout<<" update color property\n";}
    void setValue(std::integral_constant<Property, Property::StrokeColor> type,
                  const std::string &obj,
                  Color col){std::cout<<" update stroke color property\n";}
    void setValue(std::integral_constant<Property, Property::Opacity> type,
                  const std::string &obj,
                  Value opacity){std::cout<<" update opacity property\n";}
};

int main()
{
    Dom domObj;
    // try to update the color property of rect1 object inside layer1
    domObj.setValue<Property::Color>("layer1.rect1", Color());

    // compile time error expects Color value but given Size value
    //domObj.setValue<Property::Color>("layer1.rect1", Size());
    return 0;
}