rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.51k stars 702 forks source link

Template specialization #24

Open n3f4s opened 8 years ago

n3f4s commented 8 years ago

Hi, bindgen ignore template specialization for class (and struct) and select the first "working answer". For example :

template <typename T>
class test;

template<>
class test<int> {
    int foo;
};
template<>
class test<float> {
    float foo;
};

give

test.hpp:1:9: warning: #pragma once in main file [-Wpragma-once-outside-header]
/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy)]
pub struct Struct_test {
    pub foo: ::std::os::raw::c_int,
}
impl ::std::clone::Clone for Struct_test {
    fn clone(&self) -> Self { *self }
}
#[test]
fn bindgen_test_layout_Struct_test() {
    assert_eq!(::std::mem::size_of::<Struct_test>() , 4usize);
    assert_eq!(::std::mem::align_of::<Struct_test>() , 4usize);
}

The float specialization is ignored. And with a valid test<T>:

template <typename T>
class test{};

template<>
class test<int> {
    int foo;
};
template<>
class test<float> {
    float foo;
};

gives :

test.hpp:1:9: warning: #pragma once in main file [-Wpragma-once-outside-header]
/* automatically generated by rust-bindgen */

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Struct_test<T> {
    pub _phantom0: ::std::marker::PhantomData<T>,
}

Both the float and int specialization are ignored.

emilio commented 8 years ago

Yep, given template specialization is not available for rust (at least for stable), we can't do better than that.

Leaving this open so when it gets stabilized we aim to do something smarter. Until then there's not too much we can do that doing the generic one if found or the first instantiation if not :/

emilio commented 8 years ago

Oh, btw, thanks for filling this bugs, they're really useful :)

n3f4s commented 8 years ago

Would it be possible to do the same as with function (appending something at the end of the class name) ?

(Off-Topic but I don't know where to ask : once there is template specialization for rust, is it possible to use it for handling c++ overload... instead of generating multiple functions ?)

emilio commented 8 years ago

Yes, it would but then in rust you have MyTemplate<i32> and MyTemplate_int, and only the second is valid, which is clunky. Also, partial template specialization would be funny to handle.

Regarding the C++ function overloads... yes, I guess so (though it has to be written :P).

n3f4s commented 8 years ago

I was going to say that bindgen add a postfix to C++ template function, I checked to be sure and I saw that not specialized template function are not handled (same reason as template class I guess).

For C++ function overload, it would make more sense to use template specialization (IMHO). Having one (rust) function by (C++) overload would weird (having X functions with some obviously computer-generated postfix is not the best), and would cause function bloat in some case.

pvdrz commented 2 years ago

I'm not sure If bindgen can properly support this. One thing that comes to mind would be monomorphizing everything under different names so that

template <typename T>
class test{};

template<>
class test<int> {
    int foo;
};
template<>
class test<float> {
    float foo;
};

becomes

struct Test<T> {}
struct TestInt { foo: c_int }
struct TestFloat { foo: c_float }

but I don't think this is a proper solution.

n3f4s commented 2 years ago

Unless rust add generic specialisation, I also don't think there's a good solution.

I think adding a warning when template specialisation is encountered in C++ code is required tho. Having code be silently ignored isn't good :).