8

Is there a feature in Rust that makes something like this possible? As far as I know, this is not possible with Rust's generic functions because they work only with data types and not with values.

#include <iostream>

template<int T>
int foo(int a)
{
  return -1;
}
template<>
int foo<2>(int a)
{
  return a*a;
}
template<>
int foo<3>(int a)
{
  return a*a*a;
}

int main()
{
  std::cout << "foo<1>(3): "<<foo<1>(3) << std::endl;
  std::cout << "foo<2>(3): "<<foo<2>(3) << std::endl;
  std::cout << "foo<3>(3): "<<foo<3>(3) << std::endl;
  return 1;
}

Result:

foo<1>(3): -1
foo<2>(3): 9
foo<3>(3): 27
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Darius Duesentrieb
  • 837
  • 10
  • 20
  • 4
    not implemented yet: ["Tracking issue for const generics (RFC 2000)"](https://github.com/rust-lang/rust/issues/44580) – Stefan Dec 06 '17 at 13:39

1 Answers1

14

TL;DR: Not yet, maybe not ever.

Rust generics are not as powerful, yet, as C++ templates, and may never be.

Specifically here, two features are required:

Note: it is unclear how advanced the specialization will be; in this specific case where you use full specialization it should be enough, however it is not clear whether partial specialization will be implemented, and how.


There are also other missing pieces, though not related to this case:

  • RFC 1598: Generic Associated Types: equivalent to nested template <...> using ... = ...; and allowing to emulate template template parameters,
  • variadics: there have been multiple RFCs, but none seems to have gain much foothold.

It would be easy to deride Rust developers, or shrug it off as a lack of maturity; it would also be incorrect.

As I mentioned, it is not clear that Rust will ever gain some of those features, not because the developers could not implement them, they certainly could, they certainly could have already, but because there is a strong focus in doing things right1.

For example, specialization is a nightmare in C++. It is Undefined Behavior to instantiate a template with a set of arguments A, and later (or in another translation unit) specialize it in a way that would match A. For functions, this generally manifests as the linker picking either the generic or the specialized version... randomly. It's not fun to debug.

Any modifications to generics has large potential repercussions on the rest of the type system, complex interactions with other language features, and significant changes about what a well-typed program means:

  • they are therefore heavily scrutinized,
  • and there is a strong push toward going slow and building incrementally, so as to evaluate those impacts, interactions and changes one at a time.

In short, Rust developers are attempting to build a well-principled generics system, and it's not easy.

1 There are also concerns about unnecessary complexity, so features are not added "just because", but require motivating use cases which should be compelling enough to justify the additional complexity in the language and the compiler; but that's another gate entirely.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722