如何防止 C++ 中的模板类型扩展?
How can I prevent template type expansion in C++?
我写了下面的类,它使用了成员指针函数:
#include <stdlib.h>
#include <vector>
template<class Type>
class PrimitiveAccessor {
public :
PrimitiveAccessor(
JNIEnv* env, const char name[], const char ctorSig[],
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID)
) {
this->env = env;
this->type = (jclass)env->NewGlobalRef(env->FindClass(name));
this->callTypeMethodFunction = callTypeMethodFunction;
}
~PrimitiveAccessor(){
env->DeleteGlobalRef(this->type);
}
private:
JNIEnv* env;
jclass type;
jmethodID constructorId;
jmethodID callTypeMethodId;
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID);
};
class Environment {
public:
Environment(JNIEnv* env) {
this->env = env;
this->init();
}
~Environment(){
this->env = 0;
delete(this->jintAccessor);
this->jintAccessor = 0;
}
private:
JNIEnv* env;
PrimitiveAccessor<jint>* jintAccessor;
void init() {
jintAccessor = new PrimitiveAccessor<jint>(
env, "java/lang/Integer",
"(I)V", &JNIEnv::CallIntMethod
);
}
};
但是在编译时出现以下编译错误:
F:\Shared\Workspaces\Projects\DriverFunctionSupplierNative.cpp: In member function 'void Environment::init()':
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:75:4: error: no matching function for call to 'PrimitiveAccessor<long int>::PrimitiveAccessor(JNIEnv*&, const char [18], const char [5], jint (JNIEnv_::*)(jobject, jmethodID, ...))'
);
^
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:36:3: note: candidate: 'PrimitiveAccessor<Type>::PrimitiveAccessor(JNIEnv*, const char*, const char*, Type (JNIEnv_::*)(jobject, jmethodID)) [with Type = long int; JNIEnv = JNIEnv_; jobject = _jobject*; jmethodID = _jmethodID*]'
PrimitiveAccessor(
^~~~~~~~~~~~~~~~~
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:36:3: note: no known conversion for argument 4 from 'jint (JNIEnv_::*)(jobject, jmethodID, ...)' {aka 'long int (JNIEnv_::*)(_jobject*, _jmethodID*, ...)'} to 'long int (JNIEnv_::*)(jobject, jmethodID)' {aka 'long int (JNIEnv_::*)(_jobject*, _jmethodID*)'}
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:34:7: note: candidate: 'constexpr PrimitiveAccessor<long int>::PrimitiveAccessor(const PrimitiveAccessor<long int>&)'
class PrimitiveAccessor {
^~~~~~~~~~~~~~~~~
我通过转换成员函数指针临时修复了它:
void init() {
jintAccessor = new PrimitiveAccessor<jint>(
env, "java/lang/Integer",
"(I)V", (long (JNIEnv::*) (jobject, jmethodID))&JNIEnv::CallIntMethod
);
}
我注意到传递给模板的类型被扩展了:有没有办法避免这种转换?
您需要指定匹配类型,而不是相似类型。
我还清理了您的许多单调的 C++。不要使用 new
;这不是必需的。如果您的数据成员自行清理,则不需要用户定义的析构函数。您应该在成员初始化列表中初始化您的数据成员,而不是在构造函数的主体中。对字符串使用 std::string
。
#include <stdlib.h>
#include <vector>
#include <memory>
#include <string>
struct GlobalRefDeleter {
JNIEnv* env;
void operator()(jobject type) {
env->DeleteGlobalRef(type);
}
};
using JClass = std::unique_ptr<_jclass, GlobalRefDeleter>;
JClass getClass(JNIEnv* env, const std::string & name) {
return { static_cast<jclass>(env->NewGlobalRef(env->FindClass(name.c_str()))), env };
}
template<class Type>
class PrimitiveAccessor {
using CallMethod = Type (JNIEnv::*) (jobject, jmethodID, ...);
public :
PrimitiveAccessor(
JNIEnv* env, const std::string & name, const std::string & ctorSig,
CallMethod callMethod)
) : env(env), type(getClass(env, name)), callMethod(callMethod)
{
}
private:
JNIEnv* env;
JClass type;
jmethodID constructorId;
jmethodID callTypeMethodId;
CallMethod callMethod;
};
class Environment {
public:
Environment(JNIEnv* env) : env(env), jintAccessor(env, "java/lang/Integer", "(I)V", &JNIEnv::CallIntMethod)
{
}
private:
JNIEnv* env;
PrimitiveAccessor<jint> jintAccessor;
};
我写了下面的类,它使用了成员指针函数:
#include <stdlib.h>
#include <vector>
template<class Type>
class PrimitiveAccessor {
public :
PrimitiveAccessor(
JNIEnv* env, const char name[], const char ctorSig[],
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID)
) {
this->env = env;
this->type = (jclass)env->NewGlobalRef(env->FindClass(name));
this->callTypeMethodFunction = callTypeMethodFunction;
}
~PrimitiveAccessor(){
env->DeleteGlobalRef(this->type);
}
private:
JNIEnv* env;
jclass type;
jmethodID constructorId;
jmethodID callTypeMethodId;
Type (JNIEnv::*callTypeMethodFunction) (jobject, jmethodID);
};
class Environment {
public:
Environment(JNIEnv* env) {
this->env = env;
this->init();
}
~Environment(){
this->env = 0;
delete(this->jintAccessor);
this->jintAccessor = 0;
}
private:
JNIEnv* env;
PrimitiveAccessor<jint>* jintAccessor;
void init() {
jintAccessor = new PrimitiveAccessor<jint>(
env, "java/lang/Integer",
"(I)V", &JNIEnv::CallIntMethod
);
}
};
但是在编译时出现以下编译错误:
F:\Shared\Workspaces\Projects\DriverFunctionSupplierNative.cpp: In member function 'void Environment::init()':
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:75:4: error: no matching function for call to 'PrimitiveAccessor<long int>::PrimitiveAccessor(JNIEnv*&, const char [18], const char [5], jint (JNIEnv_::*)(jobject, jmethodID, ...))'
);
^
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:36:3: note: candidate: 'PrimitiveAccessor<Type>::PrimitiveAccessor(JNIEnv*, const char*, const char*, Type (JNIEnv_::*)(jobject, jmethodID)) [with Type = long int; JNIEnv = JNIEnv_; jobject = _jobject*; jmethodID = _jmethodID*]'
PrimitiveAccessor(
^~~~~~~~~~~~~~~~~
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:36:3: note: no known conversion for argument 4 from 'jint (JNIEnv_::*)(jobject, jmethodID, ...)' {aka 'long int (JNIEnv_::*)(_jobject*, _jmethodID*, ...)'} to 'long int (JNIEnv_::*)(jobject, jmethodID)' {aka 'long int (JNIEnv_::*)(_jobject*, _jmethodID*)'}
F:\Shared\Workspaces\Projects\JNIDriverFunctionSupplierNative.cpp:34:7: note: candidate: 'constexpr PrimitiveAccessor<long int>::PrimitiveAccessor(const PrimitiveAccessor<long int>&)'
class PrimitiveAccessor {
^~~~~~~~~~~~~~~~~
我通过转换成员函数指针临时修复了它:
void init() {
jintAccessor = new PrimitiveAccessor<jint>(
env, "java/lang/Integer",
"(I)V", (long (JNIEnv::*) (jobject, jmethodID))&JNIEnv::CallIntMethod
);
}
我注意到传递给模板的类型被扩展了:有没有办法避免这种转换?
您需要指定匹配类型,而不是相似类型。
我还清理了您的许多单调的 C++。不要使用 new
;这不是必需的。如果您的数据成员自行清理,则不需要用户定义的析构函数。您应该在成员初始化列表中初始化您的数据成员,而不是在构造函数的主体中。对字符串使用 std::string
。
#include <stdlib.h>
#include <vector>
#include <memory>
#include <string>
struct GlobalRefDeleter {
JNIEnv* env;
void operator()(jobject type) {
env->DeleteGlobalRef(type);
}
};
using JClass = std::unique_ptr<_jclass, GlobalRefDeleter>;
JClass getClass(JNIEnv* env, const std::string & name) {
return { static_cast<jclass>(env->NewGlobalRef(env->FindClass(name.c_str()))), env };
}
template<class Type>
class PrimitiveAccessor {
using CallMethod = Type (JNIEnv::*) (jobject, jmethodID, ...);
public :
PrimitiveAccessor(
JNIEnv* env, const std::string & name, const std::string & ctorSig,
CallMethod callMethod)
) : env(env), type(getClass(env, name)), callMethod(callMethod)
{
}
private:
JNIEnv* env;
JClass type;
jmethodID constructorId;
jmethodID callTypeMethodId;
CallMethod callMethod;
};
class Environment {
public:
Environment(JNIEnv* env) : env(env), jintAccessor(env, "java/lang/Integer", "(I)V", &JNIEnv::CallIntMethod)
{
}
private:
JNIEnv* env;
PrimitiveAccessor<jint> jintAccessor;
};