当0 OR NULL通过模板间接传递给共享指针(shared_ptr或unique_ptr)时,调用函数失败

时间:2015-12-29 15:38:13

标签: c++ c++11 c++14

#include<iostream>
#include <memory>
#include <thread>
#include <mutex>
using namespace std;
class Linux
{
};
int f1(std::shared_ptr<Linux> spw) // call these only when
{
  //do something
  return 0;
}
double f2(std::unique_ptr<Linux> upw) // the appropriate
{
  //do something
  return 0.0;
}
bool f3(Linux* pw) // mutex is locked
{

return 0;
}

std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
using MuxtexGuard = std::lock_guard<std::mutex>;

void lockAndCallF1()
{
        MuxtexGuard g(f1m); // lock mutex for f1
        auto result = f1(static_cast<int>(0)); // pass 0 as null ptr to f1
        cout<< result<<endl;
}

void lockAndCallF2()
{
        MuxtexGuard g(f2m); // lock mutex for f2
        auto result = f2(static_cast<int>(NULL)); // pass NULL as null ptr to f2
        cout<< result<<endl;
}
void lockAndCallF3()
{
        MuxtexGuard g(f3m); // lock mutex for f2
        auto result = f3(nullptr);// pass nullptr as null ptr to f3 
        cout<< result<<endl;
} // unlock mutex
int main()
{
        lockAndCallF1();
        lockAndCallF2();
        lockAndCallF3();
        return 0;
}

以上程序编译并成功执行但是lockAndCallF1,lockAndCallF2&amp; lockAndCallF3有冗余代码。所以它可以用模板推广。我为冗余代码编写了模板函数lockAndCall而不是多个定义lockAndCallF1, lockAndCallF2 & lockAndCallF3

代码重新计算如下:

#include<iostream>
#include <memory>
#include <thread>
#include <mutex>
using namespace std;
class Linux
{
};
int f1(std::shared_ptr<Linux> spw) // call these only when
{
  //do something
  return 0;
}
double f2(std::unique_ptr<Linux> upw) // the appropriate
{
  //do something
  return 0.0;
}
bool f3(Linux* pw) // mutex is locked
{

return 0;
}

std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
using MuxtexGuard = std::lock_guard<std::mutex>;

template<typename FuncType, typename MuxType, typename PtrType>
auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))
//decltype(auto) lockAndCall(FuncType func, MuxType& mutex, PtrType ptr)
{
        MuxtexGuard g(mutex);
        return func(ptr);
}
int main()
{
        auto result1 = lockAndCall(f1, f1m, 0); //compilation failed 
        //do something
        auto result2 = lockAndCall(f2, f2m, NULL); //compilation failed
        //do something
        auto result3 = lockAndCall(f3, f3m, nullptr);
        //do something
        return 0;
}

编译失败并出现以下错误

$ g++ nullptr.cpp  --std=c++11
nullptr.cpp: In function ‘int main()’:
nullptr.cpp:39:49: error: no matching function for call to ‘lockAndCall(double (&)(std::unique_ptr<Linux>), std::mutex&, NULL)’
         auto result2 = lockAndCall(f2, f2m, NULL); //compilation failed
                                                 ^
nullptr.cpp:39:49: note: candidate is:
nullptr.cpp:29:6: note: template<class FuncType, class MuxType, class PtrType> decltype (func(ptr)) lockAndCall(FuncType, MuxType&, PtrType)
 auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))
      ^
nullptr.cpp:29:6: note:   template argument deduction/substitution failed:
nullptr.cpp: In substitution of ‘template<class FuncType, class MuxType, class PtrType> decltype (func(ptr)) lockAndCall(FuncType, MuxType&, PtrType) [with FuncType = double (*)(std::unique_ptr<Linux>); MuxType = std::mutex; PtrType = long int]’:
nullptr.cpp:39:49:   required from here
nullptr.cpp:29:82: error: could not convert ‘ptr’ from ‘long int’ to ‘std::unique_ptr<Linux>’
 auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))

Question1。为什么lockAndCall调用失败,当参数0或Null f1(std :: shared_ptr spw)和f2(std :: unique_ptr upw)分别和函数调用{{1成功调用0和NULL?}和f1(static_cast<int>(0));

Question2 lockAndCall函数扣除后FuncType的类型是什么? FuncType是函数指针的类型或std :: function?

1 个答案:

答案 0 :(得分:2)

所以你的问题是声明为:

的函数
int f1(std::shared_ptr<Linux> spw);

为什么以下代码编译:

f1(static_cast<int>(0));

但是以下没有:

template<typename FuncType, typename MuxType, typename PtrType>
auto lockAndCall(FuncType func, MuxType& mutex, PtrType ptr) -> decltype(func(ptr))
{
        MuxtexGuard g(mutex);
        return func(ptr);
}

lockAndCall( f1, f1m, 0);

原因是std::shared_ptr具有nullptr的非显式构造函数,值0的整数常量可以隐式转换为nullptr。当您间接调用f1时,通过模板函数 - 参数不是值为0的常量表达式,因此无法将其转换为nullptr。请注意,在运行时该参数中的值无关紧要,这在编译时,在计算表达式的数据类型时解析。

至于NULL cppreference.com说:

  

宏NULL是一个实现定义的空指针常量,它可以是求值为零的整数类型的整数常量表达式prvalue或类型为std :: nullptr_t的prvalue(对于C ++ 11)

     

可能的实施

 #define NULL 0
 //since C++11
 #define NULL nullptr

看起来您的实现已将NULL定义为文字0,而不是nullptr

要明确解决问题,请{0}或nullptr或更好的默认构建NULLstd::shared_ptr

std::unique_ptr