Written by
Sangwan Kwon
on
on
Rust specialization with cpp specialization
Before introducing specialization on rust
,
Let’s remind template specialization on cpp
.
Template specialization on cpp
Scalar type
How can we get scalar type’s size? Scalar type’s size is fixed at compile time, it is always same at runtime.
We can get size
via size_of.
sizeof(int)
sizeof(double)
...
Compound type (w/ length type)
We cannot get size of string
nor vector
at compile time.
So, we have to use string::length()
or vector::size()
.
std::string("foo").length()
std::vector<int>{1, 2, 3}.size()
Make them generic
Let’s make template function for getting size of variable. I will use template specialization.
- (Default) Use sizeof
- (Special type) Use member function
#include <iostream>
#include <string>
#include <vector>
template<typename T>
std::size_t size(T&& value)
{
return sizeof(T);
}
template<>
std::size_t size(std::string&& string)
{
return string.length();
}
template<typename T>
std::size_t size(std::vector<T>&& vector)
{
return vector.size();
}
Let’s run!
int main() {
// int - 4
std::cout << size(0) << std::endl;
// double - 8
std::cout << size(0.0) << std::endl;
// std::string - 4
std::cout << size(std::string("text")) << std::endl;
// std::vector - 3
std::cout << size(std::vector<int>{1, 2, 3}) << std::endl;
return 0;
}
Specialization on rust
Rust’s specialization is unstable, we should use nightly version.
The step is same with cpp.
- (Default) Use sizeof
- Rust use
default
keyword for it.
- Rust use
- (Special type) Use member function
// For unstable feature
#![feature(min_specialization)]
use std::mem::size_of;
trait Measurable {
fn size(&self) -> usize;
}
// Check default keyword
impl<T> Measurable for T {
default fn size(&self) -> usize {
// This is for scalar type
size_of::<Self>()
}
}
// Specialize vector type
impl<T> Measurable for Vec<T> {
fn size(&self) -> usize {
self.len()
}
}
// Specialize string type
impl Measurable for String {
fn size(&self) -> usize {
self.len()
}
}
Let’s run!
fn main() {
assert_eq!(Measurable::size(&true), 1);
assert_eq!(Measurable::size(&0u8), 1);
assert_eq!(Measurable::size(&0u16), 2);
assert_eq!(Measurable::size(&0u32), 4);
assert_eq!(Measurable::size(&0u64), 8);
assert_eq!(Measurable::size(&String::from("foo")), 3);
assert_eq!(Measurable::size(&vec![1, 2, 3, 4]), 4);
}