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

时间:2017-12-23 20:42:09

标签: c++

我正在尝试实现将互斥对象放在地图中的jni函数。 编译时,我得到错误“......因为jni传递一个指针”,我可以在参数中进行转换。

为什么std:map无法接受指针作为键值?

给出错误的指令是:

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;
  }

下面你可以看到日志:

 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]                                                                                                          ^

1 个答案:

答案 0 :(得分:2)

您的问题与指针无关。问题是您尝试在地图中存储的对象类型不可复制,因此您无法构建它们,然后将它们复制到地图中。相反,您可以告诉地图直接在原地构建它们:

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;
}

在此,我已使用std::map::emplacestd::pair std::piecewise_construct constructor来告诉地图构建其元素。这样,互斥锁就不会被复制到地图中。