我目前正在嘗試製作一組轉換函數,通過一次調用,可以(嘗試)將JavaScript對象(CefV8Value
)轉換爲其C++對象,並支持指針。模糊不清的模板功能專業化編譯錯誤
這裏是轉換功能(末尾指針轉換):
template<typename T>
T convert_v8value_to_cpp(const CefRefPtr<CefV8Value> &value) {};
// Explicit type conversion functions
#define V8VALUE_TO_CPP_CONVERSION(type) \
template<> type \
convert_v8value_to_cpp<type>(const CefRefPtr<CefV8Value> &value)
V8VALUE_TO_CPP_CONVERSION(CefRefPtr<CefV8Value>)
{
return value;
}
V8VALUE_TO_CPP_CONVERSION(bool)
{
return value->GetBoolValue();
}
V8VALUE_TO_CPP_CONVERSION(int)
{
return value->GetIntValue();
}
V8VALUE_TO_CPP_CONVERSION(std::string)
{
return value->GetStringValue().ToString();
}
V8VALUE_TO_CPP_CONVERSION(const char *)
{
return value->GetStringValue().ToString().c_str();
}
V8VALUE_TO_CPP_CONVERSION(std::wstring)
{
return value->GetStringValue().ToWString();
}
// HACKHACK: most VGUI functions take non-const wchar_t pointers, when they
// shouldn't
V8VALUE_TO_CPP_CONVERSION(wchar_t *)
{
return (wchar_t*)value->GetStringValue().ToWString().c_str();
}
V8VALUE_TO_CPP_CONVERSION(const wchar_t *)
{
return value->GetStringValue().ToWString().c_str();
}
V8VALUE_TO_CPP_CONVERSION(double)
{
return value->GetDoubleValue();
}
V8VALUE_TO_CPP_CONVERSION(float)
{
return value->GetDoubleValue();
}
//-----------------------------------------------------------------------------
// Purpose: converts a JS array to a C++ vector (of type T)
//-----------------------------------------------------------------------------
template<typename T>
std::vector<T> convert_v8value_to_cpp(const CefRefPtr<CefV8Value> &value)
{
std::vector<T> vec;
if(!value->IsArray())
return vec;
for(int i = 0; i < value->GetArrayLength(); ++i)
{
CefRefPtr<CefV8Value> element = value->GetValue(i);
vec.push_back(convert_v8value_to_cpp<T>(element));
}
return vec; // hopefully move semantics will optimise this and not copy-construct
}
//-----------------------------------------------------------------------------
// Purpose: converts a JS object to a C++ pointer (where T is a pointer type)
//-----------------------------------------------------------------------------
template<typename T>
typename std::enable_if<std::is_pointer<T>::value, T>::type
convert_v8value_to_cpp(const CefRefPtr<CefV8Value> &value)
{
if(!value->IsObject())
return NULL;
CefRefPtr<CefV8Value> pTypeId = value->GetValue("__v8bind_typeid__");
if(!pTypeId || !pTypeId->IsString())
return NULL;
CefRefPtr<CefV8Value> pPointerVal = value->GetValue("__v8bind_ptr__");
if(!pPointerVal || !pPointerVal->IsInt())
return NULL;
if(pTypeId->GetStringValue().ToString() == typeid(T).name())
return (T)pPointerVal->GetIntValue();
return NULL;
}
下面是一個使用該指針函數的代碼:
WrapClass *pThis = convert_v8value_to_cpp<WrapClass*>(object);
的Visual Studio抱怨說:
error C2668: 'convert_v8value_to_cpp' : ambiguous call to overloaded function
binding_test.cpp(106): could be 'Point *convert_v8value_to_cpp<WrapClass*>(const CefRefPtr<T> &)'
with
[
WrapClass=Point,
T=CefV8Value
]
binding_test.cpp(88): or 'std::vector<_Ty,_Ax> convert_v8value_to_cpp<WrapClass*>(const CefRefPtr<T> &)'
with
[
_Ty=Point *,
_Ax=std::allocator<Point *>,
WrapClass=Point,
T=CefV8Value
]
binding_test.cpp(31): or 'T convert_v8value_to_cpp<WrapClass*>(const CefRefPtr<CefV8Value> &)'
with
[
T=Point *,
WrapClass=Point
]
while trying to match the argument list '(CefRefPtr<T>)'
with
[
T=CefV8Value
]
我不明白d呼叫如何模糊(除WrapClass *
與T
的第一個轉換功能匹配外)。但是它也表示可能的候選人是std::vector
轉換。這怎麼可能?
非常感謝提前!
見下面的答案。此外,您轉換爲char *,wchar_t *和wchar_t const *會返回指向臨時的指針,這是未定義的行爲。 – Tomek
我沒有注意到,我原本以爲[W] String()函數返回引用......謝謝Tomek! – Saul