67
#include <iostream>
#include <type_traits>

int main(){

    //creating an integral constant with constexpr
    constexpr unsigned int speed_of_light{299792458};

    //creating an integral constant with std::integral_constant
    typedef std::integral_constant<unsigned int, 299792458> speed_of_light_2;

    //using them
    std::cout << speed_of_light/2 << '\n';
    std::cout << speed_of_light_2::value/2 << '\n';

}

What's special about std::integral_constant that I would choose to use it over constexpr?
Their behaviour and use cases look identical to me. I'm trying to think of some kind of template scenario, where constexpr may not suffice.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Trevor Hickey
  • 36,288
  • 32
  • 162
  • 271
  • 1
    I've never understood the use case of `std::integral_constant` to be for making integral constants. It's a TMP feature used for various kinds of things, especially tag dispatching (usually based on its specializations `std::true_type` and `std::false_type`), something a constant value cannot be used for. Of course for constants use actual constants and not some strange typified constant. – Christian Rau Dec 04 '13 at 08:24
  • There is a lot more on this at [Why does Boost MPL have integral constants?](http://stackoverflow.com/questions/14389429/why-does-boost-mpl-have-integral-constants) – Mankka Dec 15 '14 at 19:46

2 Answers2

53

Template integral_constant defines a type, keyword constexpr defines a constant. For example std::true_type is std::integral_constant<bool, true>.

One of the usage examples is tag-dispatching.

template<typename T>
void use_impl(const T&, std::false_type)
{
}

template<typename T>
void use_impl(const T&, std::true_type)
{
}

template<typename T>
void use(const T& v)
{
   use_impl(v, std::is_integral<T>());
}

Live example

Hari
  • 1,561
  • 4
  • 17
  • 26
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • But what if std::true_type was defined as "constexpr bool true_type = true; I can't see how that would change its behaviour. Maybe constexpr creates an actual instance, but integral constant just defines a type... no, I don't think so. I'm not sure. – Trevor Hickey Dec 04 '13 at 06:26
  • 3
    @TrevorHickey it will not have another type, it will simply have type bool in case of constexpr. – ForEveR Dec 04 '13 at 06:27
  • Oh, making decisions based on a value at compile time. I wonder if that behaviour can be matched using the ternary operator along with constexpr. Either way, I see its value now. – Trevor Hickey Dec 04 '13 at 06:32
  • 3
    Not in general case. The compiler (gcc at least) will attempt to instantiate objects in all the "reachable" blocks, even if optimizer is going to cull those blocks later on due to constexpr conditions. This would not happen with templated expressions, because SFINAE inference happens beforehand. – oakad Dec 04 '13 at 06:52
15

It can be used for tag dispatching along with the ternary operator.

eg

void gotoN_impl(std::integral_constant<int,0>)
{
    std::cout << "GoTo 0" << '\n';
}

void gotoN_impl(std::integral_constant<int,1>)
{
    std::cout << "GoTo 1" << '\n';
}

void gotoN_impl(std::integral_constant<int,2>)
{
    std::cout << "GoTo 2" << '\n';
}
 
void gotoN_impl(std::integral_constant<int,3>)
{
    std::cout << "GoTo 3" << '\n';
} 

template<int N>
void gotoN()
{
    gotoN_impl(std::integral_constant<int, N>());
}


int main()
{
    gotoN<0>();
    gotoN<1>();
    gotoN<2>();
    gotoN<3>();
    
    constexpr auto x = 99;
    
    gotoN<x<4?x:3>(); // with a ternary operator
}
Hari
  • 1,561
  • 4
  • 17
  • 26
QuentinUK
  • 2,997
  • 21
  • 20