1

I have the following declaration in my header file:

extern "C" {
    struct lfModifier {
        template<typename T>
        static void ModifyColor_Vignetting_PA (
           void *data, float x, float y, T *rgb, int comp_role, int count);
    }
}

GCC probably rightfully complains "error: template with C linkage". But the template is static after all. I could easily move it out of the class into the cpp file. I don't like to do that because having it in the struct increases code readability.

Is there a way to have a static template in this context?

David G
  • 94,763
  • 41
  • 167
  • 253
Torsten Bronger
  • 9,899
  • 7
  • 34
  • 41
  • even if this is possible there's no practical use for it – M.M Mar 04 '15 at 19:21
  • What do you want to accomplish by having a **member** function with C linkage? No other `extern C` member function of other class being able to share the same name? – Daniel Mar 04 '15 at 19:42
  • @Mondkin: It is about a library in C++. I think (I maintain code of somebody else) the goal is to use the same library header file for C and C++ programs. The C programs see `struct` and attributes, and the C++ programs see everything but with C linkage. Well, and then, the template member fails. – Torsten Bronger Mar 04 '15 at 19:46
  • You can't have this inside the header file anyway, since C doesn't know what a template is. And if you hide it from C using `#define`, you break the One Definition Rule. – Ben Voigt Mar 04 '15 at 19:57
  • @BenVoigt: It is hidden from C with `#ifdef __cplusplus`. – Torsten Bronger Mar 04 '15 at 20:22
  • @TorstenBronger: Then the type is different in C and in C++, but you are giving them the same name (with the same linkage) and (says the Standard) that is undefined behavior. You can try to rely on standard-layout rules to make the data members line up and create two layout-compatible types, but then they are still separate types which require separate names. – Ben Voigt Mar 04 '15 at 20:36
  • @BenVoigt, this may be true, however, this is another issue, which requires in-depth analysis that we cannot do in SO comments. My code above is heavily simplified of course. – Torsten Bronger Mar 04 '15 at 20:40

3 Answers3

1

If you need other members in the struct to have C linkage, the template function can have C++ linkage.

extern "C" {
    struct lfModifier {
        int val;
        void foo();

        extern "C++" template<typename T>
        static void ModifyColor_Vignetting_PA (
           void *data, float x, float y, T *rgb, int comp_role, int count);
    }
}

extern C++ for a member of a struct will override the extern C attribute of the struct.

mostafa.elhoushi
  • 3,758
  • 1
  • 17
  • 10
0
// Inside header
extern "C" { struct X; };
struct X {
    template <typename T> static void f() {}
};

// Inside cpp
int main() {
    X::f<int>();
}
tohava
  • 5,344
  • 1
  • 25
  • 47
  • 2
    while this codeblock might answer the question, please try to add relevant explanation. – SMR Mar 05 '15 at 07:40
0

I don't think it's possible.

Check this other question and its answer: In C++ source, what is the effect of extern "C"?

The most important parts from there:

  • extern "C" is ignored for class members
  • at most one function with a particular name can have "C" linkage (regardless of namespace)
  • 'static' inside 'extern "C"' is valid; an entity so declared has internal linkage, and so does not have a language linkage

The most important there is the one in the middle: when you instantiate your template you would have two functions with the same name, but different parameters, which is not directly supported by C. So the C++ compiler needs to mangle the name for templated functions.

Also, when you declare your function outside the struct and you say it is static you are giving it internal linkage, so the extern C will be ignored (that's the reason why it compiles in that case). Have you used objdump to see the compiled name to make sure it is not being mangled?

Community
  • 1
  • 1
Daniel
  • 21,933
  • 14
  • 72
  • 101