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

Wha*_*rld 10 c++ std

真正的用例是什么?

std::integral_constant
Run Code Online (Sandbox Code Playgroud)

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

typedef std::integral_constant<int, 2> two_t
Run Code Online (Sandbox Code Playgroud)

但是为什么不只使用2或用2定义const int值呢?

Jus*_*tin 11

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

标签分发就是其中之一。例如,std::true_typestd::false_type分别是std::integral_constant<bool, true>std::integral_constant<bool, false>。每个类型特征都std::true_type或派生std::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>{});
}
Run Code Online (Sandbox Code Playgroud)

同样,模板元编程库通常只对类型列表而不是值列表使用算法。如果您想将这些算法用于值,则必须使用类似std::integral_constant

  • @WhatABeautifulWorld 不。你甚至可以做一些事情,比如在不同的实现中返回不同的类型。那不会只用一个 `if` 编译。然而,在 C++17 中,我们得到了 `if constexpr`,它适用于这个用例。 (2认同)

R S*_*ahu 7

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

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

更重要的是,std::true_typestd::false_type是使用最广泛的专长std::integral_constant。它们广泛用于type_traits.


小智 5

下面的代码片段是我使用 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;
}
Run Code Online (Sandbox Code Playgroud)