Domanda

I need to implement the following interface

struct mutex;
struct interface
{
  //...
  mutex& getMutex();
};

Intuition would I could use using mutex = ParticularMutex in my implementation, but gcc tells me otherwise:

error: conflicting declaration ‘using mutex = ’
error: ‘class mutex’ has a previous declaration as ‘class mutex’

I am not defining anything twice, only declaring twice, as usual when forward declaring, so

  1. why doesn't this work?
  2. is there a workaround without modifying interface?
  3. how should interface have been defined? with template <typename mutex>?
È stato utile?

Soluzione

  1. It does not work because the forward declaration struct mutex; tells the compiler that mutex is a new type. With using you are then creating a type alias, which means it's not a new type (as promised to the compiler), but an alias to an existing type.

  2. No.

  3. Yes.


What you could do is:

struct mutex : ParticularMutex {
    using ParticularMutex::ParticularMutex; // inherit constructors
};

Which does define a type derived from ParticularMutex which is hopefully compatible enough. Of course, this is a new type which might lead to other problems.

Altri suggerimenti

In a similar situation (working with JNI abstraction), here is what I do:

JNI-unaware file MyObject.h:

class PlatformObject; // forward declaration
struct MyObject {
        int accumulator;
        PlatformObject* platformObj;
};

JNI-aware file jniBridge.cpp:

#include <jni.h>
#define PlatformObject _jobject
#include "MyObject.h"

void attach(MyObject& obj, jobject parent) {
    obj.platformObj = env->GetObjectField(parent, child_FieldID);
}

void add(MyObject& obj, int k) {
    accumulator += k;
    env->CallVoidMethod(obj.platformObj, add_MethodID, k);
}

The accepted answer works for add() but not for attach(); extra static_cast is required for the latter.

I believe that in some cases, both approaches have their advantages.

  • First you're saying that mutex is a specific class type. Then later you're saying "oh wait, mutex isn't its own type, it's really this other type instead". The compiler doesn't know what to do in that case.

  • Replace struct mutext with the using and it should just work (I'm not totally up to date on C++11 using).

  • If you want to be able to support multiple mutex implementations, you might want to make the interface a template (or use a mutex abstract interface that virtually decides which mutex implementation to call).

Well, you usually can solve this problem by adding a stub declaration of that ParticularMutex to one of your headers. Something like:

namespace foreignlib {
    namespace foreignsublib {
        class ParticularMutex;
    }
}

And then in your general header:

namespace ourlib {
    using mutex = foreignlib::foreignsublib::ParticularMutex;
}

This works fine and parses and compiles fast. The advantage: Whoever reads your general header knows, what this your specific mutex stands for after all. The disadvantage: You cannot write a mutex-agnostic library, where later you can drop in one or the other mutex using the using directive. If you want or need to do that, the C++ Gods want you to use templates instead. But these come at their own price...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top