Reputation: 2802
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
interface
?interface
have been defined? with template <typename mutex>
?Upvotes: 15
Views: 15017
Reputation: 2934
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...
Upvotes: 0
Reputation: 57173
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.
Upvotes: 1
Reputation: 56863
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.
No.
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.
Upvotes: 13
Reputation: 96241
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).
Upvotes: 0