简体   繁体   English

为什么std:map不能接受指针作为键值?

[英]Why std:map can't accept a pointer as key-value?

I am trying to realize a jni function putting a mutex object in a map . 我正在尝试实现将互斥对象放入地图的jni函数 When compiling, I get the error "...because jni pass a pointer" and I canmot convert in the argument. 编译时,出现错误“ ...因为jni传递了指针”,并且我无法在参数中进行转换。

Why a std:map cannot accept a pointer as key-value? 为什么std:map不能接受指针作为键值?

The instruction which gives the error is this: 给出错误的指令是这样的:

std::pair<_jobject , boost::fibers::recursive_mutex> v = 
   std::pair<_jobject , boost::fibers::recursive_mutex>(*ref, *new boost::fibers::recursive_mutex());

#include <jni.h>
#include <map>
#include "ext_concurrent_fiber_FiberLock.h"
#include <boost/fiber/recursive_mutex.hpp>
std::map<_jobject, boost::fibers::recursive_mutex> mutexes;
boost::fibers::recursive_mutex lock;
// ‘std::pair<_jobject*, boost::fibers::recursive_mutex>::
//pair(_jobject&, boost::fibers::recursive_mutex&)’
// mutexes.insert(std::pair<jobject , boost::fibers::recursive_mutex>((_jobject&)ref, *new boost::fibers::recursive_mutex()));

JNIEXPORT jboolean JNICALL Java_ext_concurrent_fiber_FiberLock_setLockIfNotPresent
  (JNIEnv * env, jclass clazz, jobject ref){
  lock.lock();
  std::map<_jobject, boost::fibers::recursive_mutex>::iterator i =mutexes.find(*ref);

    if(i == mutexes.end())
    {

        std::pair<_jobject , boost::fibers::recursive_mutex> v
        =std::pair<_jobject , boost::fibers::recursive_mutex>(*ref, *new boost::fibers::recursive_mutex());
        mutexes.insert(v);
        lock.unlock();
        return true;
    }
   lock.unlock();
   return false;
  }

Below you can see the log: 您可以在下面看到日志:

 jni:
         [echo] Generating JNI headers
         [exec] mkdir -p target/c++
         [exec] g++ -c -Wall -fPIC -I/usr/lib/jvm/java-8-oracle/include/ -I/usr/lib/jvm/java-8-oracle/include/linux -I/usr/include/boost_1_66_0  -o target/c++/ext_concurrent_fiber_NativeFiber.o src/main/c++/ext_concurrent_fiber_NativeFiber.cpp
         [exec] mkdir -p target/c++
         [exec] g++ -c -Wall -fPIC -I/usr/lib/jvm/java-8-oracle/include/ -I/usr/lib/jvm/java-8-oracle/include/linux -I/usr/include/boost_1_66_0  -o target/c++/ext_concurrent_fiber_FiberLock.o src/main/c++/ext_concurrent_fiber_FiberLock.cpp
         [exec] src/main/c++/ext_concurrent_fiber_FiberLock.cpp: In function ‘jboolean Java_ext_concurrent_fiber_FiberLock_setLockIfNotPresent(JNIEnv*, jclass, jobject)’:
         [exec] src/main/c++/ext_concurrent_fiber_FiberLock.cpp:21:105: error: no matching function for call to ‘std::pair<_jobject, boost::fibers::recursive_mutex>::pair(_jobject&, boost::fibers::recursive_mutex&)’
         [exec]         =std::pair<_jobject , boost::fibers::recursive_mutex>(*ref, *new boost::fibers::recursive_mutex());
         [exec]                                                                                                          ^
         [exec] In file included from /usr/include/c++/6/bits/stl_algobase.h:64:0,
         [exec]                  from /usr/include/c++/6/bits/stl_tree.h:63,
         [exec]                  from /usr/include/c++/6/map:60,
         [exec]                  from src/main/c++/ext_concurrent_fiber_FiberLock.cpp:3:
         [exec] /usr/include/c++/6/bits/stl_pair.h:423:9: note: candidate: template<class ... _Args1, long unsigned int ..._Indexes1, class ... _Args2, long unsigned int ..._Indexes2> std::pair<_T1, _T2>::pair(std::tuple<_Args1 ...>&, std::tuple<_Args2 ...>&, std::_Index_tuple<_Indexes1 ...>, std::_Index_tuple<_Indexes2 ...>)
         [exec]          pair(tuple<_Args1...>&, tuple<_Args2...>&,
         [exec]          ^~~~
         [exec] /usr/include/c++/6/bits/stl_pair.h:423:9: note:   template argument deduction/substitution failed:
         [exec] src/main/c++/ext_concurrent_fiber_FiberLock.cpp:21:105: note:   ‘_jobject’ is not derived from ‘std::tuple<_Args1 ...>’
         [exec]         =std::pair<_jobject , boost::fibers::recursive_mutex>(*ref, *new boost::fibers::recursive_mutex());
         [exec]                                                                                                          ^
         [exec] In file included from /usr/include/c++/6/bits/stl_algobase.h:64:0,
         [exec]                  from /usr/include/c++/6/bits/stl_tree.h:63,
         [exec]                  from /usr/include/c++/6/map:60,
         [exec]                  from src/main/c++/ext_concurrent_fiber_FiberLock.cpp:3:
         [exec] /usr/include/c++/6/bits/stl_pair.h:356:9: note: candidate: template<class ... _Args1, class ... _Args2> std::pair<_T1, _T2>::pair(std::piecewise_construct_t, std::tuple<_Args1 ...>, std::tuple<_Args2 ...>)
         [exec]          pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
         [exec]          ^~~~
         [exec] /usr/include/c++/6/bits/stl_pair.h:356:9: note:   template argument deduction/substitution failed:
         [exec] src/main/c++/ext_concurrent_fiber_FiberLock.cpp:21:105: note:   ‘boost::fibers::recursive_mutex’ is not derived from ‘std::tuple<_Args1 ...>’
         [exec]         =std::pair<_jobject , boost::fibers::recursive_mutex>(*ref, *new boost::fibers::recursive_mutex());
         [exec]                                                                                                          ^

Your issue has nothing to do with pointers. 您的问题与指针无关。 The problem is that the object types you're trying to store in your map are not copyable, so you can't construct them and then copy them into the map. 问题在于您要存储在地图中的对象类型不可复制,因此您无法构造它们然后将它们复制到地图中。 Instead, you can tell the map to construct them directly in place: 相反,您可以告诉地图直接在原位构造它们:

std::map<jobject, boost::fibers::recursive_mutex> mutexes;
boost::fibers::recursive_mutex lock;

JNIEXPORT jboolean JNICALL
Java_ext_concurrent_fiber_FiberLock_setLockIfNotPresent(JNIEnv* env, jclass clazz, jobject ref)
{
    std::lock_guard<boost::fibers::recursive_mutex> lck(lock);

    auto i = mutexes.find(ref);
    if(i == mutexes.end())
    {
        mutexes.emplace(std::piecewise_construct,
                        std::forward_as_tuple(ref),
                        std::tuple<>{});
        return true;
    }
    return false;
}

Here, I've used std::map::emplace along with std::pair 's std::piecewise_construct constructor to tell the map to construct its elements in place. 在这里,我使用了std::map::emplace以及std::pairstd::piecewise_construct构造函数来告诉地图就位构造其元素。 That way, the mutex won't need to be copied into the map. 这样,就不需要将互斥锁复制到地图中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM