我相信我有一个理想的解决方案。它只需要改变测试功能,所以它只保留SmartPtr和Variant,这是理想的。它将一个未定义的模板化重载添加到测试中,该测试对已定义的bool和nullptr进行了专门化。这直接调度bool和nullptr到所需的专业化,但会导致其他未处理类型的链接错误。我很高兴能解决这个问题,因为我自己已经以多种形式遇到过这个问题。我希望你可以使用显式的函数参数!
我从这里的想法:我已经有不理想的东西回答C++ templates that accept only certain types
using namespace std;
class Object
{
public:
};
class Variant
{
public:
Variant(bool b) : _b(b) { }
private:
bool _b;
};
template<typename T>
class SmartPtr
{
public:
SmartPtr(std::nullptr_t null) { p_ = nullptr; }
template<typename Y>
SmartPtr(Y* p) { p_ = p; }
private:
T* p_;
};
class Obj
{
public:
void test(SmartPtr<Object> here /*p*/) {
cout << "smartptr version!" << endl;
}
void test(Variant /*v*/) { cout << "variant version!" << endl; }
template<typename T> void test(T t);
template<>
void test<bool>(bool b) {
cout << "bool specialization" << endl;
test(Variant(b));
}
template<>
void test<std::nullptr_t>(std::nullptr_t null) {
cout << "nullptr specialization" << endl;
test(SmartPtr<Object>(nullptr));
}
};
int main(int argc, const char *argv[])
{
Obj o;
Obj c;
Object object;
//o.test(3); // Gives link error LNK2019
o.test(Variant(true)); // calls Variant version
o.test(SmartPtr<Object>(&object)); // calls SmartPtr version
o.test(nullptr); // dispatched to SmartPtr version by nullptr specialization
o.test(true); // dispatched to Variant version by bool specialization
o.test(false); // dispatched to Variant version by bool specialization
return 0;
}
,所以我留在机智这个问题的答案是什么如下:
======= ======================================
我没有理想的解决方案在这里,我不知道你对代码有什么限制,所以这可能不会对你有用,但以下是明智的。它不允许代码在编译时使用nullptr,并且依赖全局null_smart常量用于所有调用者只是无意传递对象的情况。
#include <iostream>
using namespace std;
class Object
{
public:
};
class Variant
{
public:
Variant(bool b) : _b(b) { }
private:
Variant(std::nullptr_t) {};
private:
bool _b;
};
template<typename T>
class SmartPtr
{
public:
SmartPtr() { p_ = nullptr; }
template<typename Y>
SmartPtr(Y* p) { p_ = p; }
private:
T* p_;
};
class Obj
{
public:
void test(SmartPtr<Object> /*p*/) { cout << "smartptr version!" << endl; }
void test(Variant /*v*/) { cout << "variant version!" << endl; }
};
const SmartPtr<Object> null_smart;
int main(int argc, const char *argv[])
{
Obj o;
o.test(null_smart); // calls SmartPtr version, without interest in passing object
o.test(true); // calls Variant version
o.test(false); // calls Variant version
return 0;
}
它比真/变异(错误)问题更清洁,但在挑剔的一面仍然有点。
不同的编译器对待这段代码的方式不同。 g ++(C++ 1y)在'nullptr'和'false'都失败。 clang(C++ 1y)在'nullptr'失败。相关问题:http://stackoverflow.com/questions/17501942/false-implicitly-convert-to-null-pointer/ – zch 2014-08-28 12:56:08
我认为符合标准的编译器应该接受整个代码('nullptr_t - > SmartPtr'优于'nullptr_t - > bool - > Variant和'bool - > nullptr_t - > SmartPtr'无效),但我想这对你没有多大帮助。我会建议使用单独的函数名称。 – zch 2014-08-28 13:24:21
@zsh:我在linux上使用clang和g ++以及std = C++ 11以及windows上的vc12,错误消息也是一样的。不幸的是,不同的命名是不成问题的,因为之前的代码工作正常,我尝试为SmartPtr类引入nullptr_t构造函数,从而导致编译失败。 – mgr 2014-08-29 07:20:50