ssb
ssb

Reputation: 7502

How does one replicate C++'s template based SFINAE pattern in Rust?

I have the following:

trait Runnable {
    fn run(&self);
}

struct Foo<T> {
    // Something
}

impl<T> Runnable for Foo<T>
where
    T: Send + Sync,
{
    fn run(&self) {}
}

impl<T> Runnable for Foo<T>
where
    T: Send + ?Sync,
{
    fn run(&self) {}
}

The compiler complains about a duplicate impl even though the T is mutually exclusive in both cases:

error[E0119]: conflicting implementations of trait `Runnable` for type `Foo<_>`:
  --> src/main.rs:16:1
   |
9  | / impl<T> Runnable for Foo<T>
10 | | where
11 | |     T: Send + Sync,
12 | | {
13 | |     fn run(&self) {}
14 | | }
   | |_- first implementation here
15 | 
16 | / impl<T> Runnable for Foo<T>
17 | | where
18 | |     T: Send + ?Sync,
19 | | {
20 | |     fn run(&self) {}
21 | | }
   | |_^ conflicting implementation for `Foo<_>`

Upvotes: 1

Views: 886

Answers (1)

mcarton
mcarton

Reputation: 30001

What you want is specialization:

#![feature(specialization)]

trait Runnable {
    fn run(&self);
}

struct Foo<T> {
    _t: T,
}

impl<T> Runnable for Foo<T>
where
    T: Send + Sync,
{
    fn run(&self) {}
}

impl<T> Runnable for Foo<T>
where
    T: Send,
{
    default fn run(&self) {}
//  ^^^^^^^ this is the magic you need
}

fn main() {}

However, as of Rust 1.26.2, specialization is not stable and requires a nightly compiler.

Upvotes: 4

Related Questions