Try to use C++ template class into swift with a specialization

Hello I was trying to import a C++ .h (the library that I want to use) that is a template class and specialize this class in Swift so that I have the C++ class only with floats. I'm doing this on Ubuntu so I compile from terminal. I don't know which is the correct way to do it but after I read the documentation here, I did this:

module cppClassLib {
    header "cppClass.h"

    export *
}

then in the Swift file I did

import cppClassLib

struct CppClass<Float>{
    func printHello(){
        print("Hello")
    }
}

The C++ class is kind of this:

cppClass.h

template <class T> class CppClass {
     // Some methods
}

I don't know if this is the correct way but it seems that is the only way to make it compile. If now I create a variable of type CppClass<Float> I can call the printHello but I cannot call any method that is inside the CppClass in the .h file.

If someone can help me I will be really grateful.

Thanks

Hello @thomas945, thanks a lot for your answer, I did what you suggested but I'm getting an error on typealias CppClassFloat = CppClass<Float>, it says:

CppClass is unavailable: Un-specialized class templates are not currently supported. Please use a specialization of this type.

Do you know why I'm getting this? I thought that I was specializing the class passing the Float parameter.

Swift currently doesn’t support specializing C++ template types directly in Swift code (as I understand it, the generics models are different enough that this doesn’t work well). However, you can do this:

// C++ header
using CppClassFloat = CppClass<float>;
// Swift file
extension CppClassFloat {
    // …
}
5 Likes

Thanks for the answer.
Yes, in the end, this is what I have done!

@j-f1 Do you know if it is possible to make some public methods that I have in the cpp class not available in Swift? Kind of making them private in Swift?
Thanks

You can try adding NS_REFINED_FOR_SWIFT if you want to make them available but with an __ prefix (which allows you to recreate them in an extension in Swift with a different type or different semantics), or NS_SWIFT_UNAVAILABLE to hide them entirely. Both of those macros are in Foundation, but there are CoreFoundation versions with the CF prefix if you’d prefer not to have the Objective-C stuff in your headers, and you can always copy out the underlying __attribute__ declarations from the header into your own macro for cross-platform code.

Hello, thanks for you answer, but I did not understand how to proceed to use this... Should I have the Objective-C bridge? Because in my project I have only C++ and Swift code.

Thanks

You don’t need an Objective-C bridge. If you’re targeting only Apple platforms, you can #import <CoreFoundation/CoreFoundation.h> to use the CF_REFINED_FOR_SWIFT and CF_SWIFT_UNAVAILABLE macros, or copy and paste them into your own project (ideally after changing the CF prefix to avoid name conflicts) from their sources (source 1, source 2):

#if __has_feature(attribute_availability_swift)
# define CF_SWIFT_UNAVAILABLE(_msg) __attribute__((availability(swift, unavailable, message=_msg)))
#else
# define CF_SWIFT_UNAVAILABLE(_msg)
#endif
#if __has_attribute(swift_private)
# define CF_REFINED_FOR_SWIFT __attribute__((swift_private))
#else
# define CF_REFINED_FOR_SWIFT
#endif