[英]explicit template specialization from function template not working
I am trying to do explicit specialization for a template function called from another template function. 我正在尝试对从另一个模板函数调用的模板函数进行显式专门化。 Following is a minimum non-working example and I am trying to implement the following idea:
以下是一个最小的无效示例,我正在尝试实现以下想法:
CInt
, CDouble
and CStr
are equivalent of operations that I need to perform. CInt
, CDouble
和CStr
等效于我需要执行的操作。 But, CStr
constructor expects a little different format. 但是,
CStr
构造函数期望格式略有不同。 MyClass
is equivalent of a factory, which when requested will return one of the instances of CInt
, CDouble
or CStr
. MyClass
等效于工厂,当请求工厂时,它将返回CInt
, CDouble
或CStr
的实例之一。
The motivation for this structure: Assume that GetCClass
function is called from a function with ~100 lines and only one difference: the type of class. 这种结构的动机:假设从大约100行的函数中调用
GetCClass
函数,并且只有一个区别:类的类型。 The values returned from GetCClass
have same APIs. 从
GetCClass
返回的值具有相同的API。
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class CStrArg {
public:
const char* a;
int size;
};
class MyClass {
public:
class CStr;
class CInt;
class CDouble;
template <typename T>
typename T::Ptr GetCClass(typename T::ArgType arg);
template <typename T>
typename T::Ptr GetCClassInternal(typename T::ArgType arg);
};
class MyClass::CInt {
public:
typedef int ArgType;
typedef shared_ptr<CInt> Ptr;
static Ptr CreatePtr(ArgType i) { return Ptr(new CInt(i)); }
private:
CInt(ArgType i) : i_(i) {}
ArgType i_;
};
class MyClass::CDouble {
public:
typedef double ArgType;
typedef shared_ptr<CDouble> Ptr;
static Ptr CreatePtr(ArgType d) { return Ptr(new CDouble(d)); }
private:
CDouble(ArgType i) : i_(i) {}
ArgType i_;
};
class MyClass::CStr {
public:
typedef CStrArg ArgType;
typedef shared_ptr<CStr> Ptr;
static Ptr CreatePtr(string s) { return Ptr(new CStr(s)); }
private:
CStr(string i) : i_(i) {}
string i_;
};
//template definition
template <typename T>
typename T::Ptr MyClass::GetCClass(typename T::ArgType arg) {
return GetCClassInternal(arg);
}
template <typename T>
typename T::Ptr MyClass::GetCClassInternal(typename T::ArgType arg) {
cout << "GetCClass for all types but one" << endl;
return T::CreatePtr(arg);
}
template <>
MyClass::CStr::Ptr MyClass::GetCClassInternal<MyClass::CStr>(CStrArg arg) {
return CStr::CreatePtr(arg.a);
}
int main() {
MyClass test;
int i = 5;
double d = 1.2;
CStrArg s;
s.a = "why me";
s.size = 6;
auto iptr = test.GetCClass(i);
auto dptr = test.GetCClass(d);
auto sptr = test.GetCClass(s);
return 0;
}
I get the following error: 我收到以下错误:
experimental/amandeep/proto_test/fn_template_sp.cc:88:31: note: candidate is:
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template<class T> typename T::Ptr MyClass::GetCClass(typename T::ArgType)
typename T::Ptr GetCClass(typename T::ArgType arg);
^
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template argument deduction/substitution failed:
experimental/amandeep/proto_test/fn_template_sp.cc:88:31: note: couldn't deduce template parameter ‘T’
auto iptr = test.GetCClass(i);
^
experimental/amandeep/proto_test/fn_template_sp.cc:89:31: error: no matching function for call to ‘MyClass::GetCClass(double&)’
auto dptr = test.GetCClass(d);
^
experimental/amandeep/proto_test/fn_template_sp.cc:89:31: note: candidate is:
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template<class T> typename T::Ptr MyClass::GetCClass(typename T::ArgType)
typename T::Ptr GetCClass(typename T::ArgType arg);
^
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template argument deduction/substitution failed:
experimental/amandeep/proto_test/fn_template_sp.cc:89:31: note: couldn't deduce template parameter ‘T’
auto dptr = test.GetCClass(d);
^
experimental/amandeep/proto_test/fn_template_sp.cc:90:31: error: no matching function for call to ‘MyClass::GetCClass(CStrArg&)’
auto sptr = test.GetCClass(s);
^
experimental/amandeep/proto_test/fn_template_sp.cc:90:31: note: candidate is:
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template<class T> typename T::Ptr MyClass::GetCClass(typename T::ArgType)
typename T::Ptr GetCClass(typename T::ArgType arg);
^
experimental/amandeep/proto_test/fn_template_sp.cc:20:19: note: template argument deduction/substitution failed:
experimental/amandeep/proto_test/fn_template_sp.cc:90:31: note: couldn't deduce template parameter ‘T’
auto sptr = test.GetCClass(s);
I have read multiple answers, but I cannot understand why this is not working. 我已经阅读了多个答案,但是我不明白为什么它不起作用。 Any help is appreciated.
任何帮助表示赞赏。
EDIT: I cannot understand, but locally in my actual code I get the following: 编辑:我不明白,但是在我的实际代码中,我得到以下信息:
/home/workspace/main/util/storage/smb2_proxy/smb2_proxy.cc:239:29: error: template-id ‘CreateOp<storage::smb2_proxy::Smb2Proxy::PurgeTaskOp>’ for ‘storage::smb2_proxy::Smb2Proxy::PurgeTaskOp::Ptr storage::smb2_proxy::Smb2Proxy::CreateOp(std::shared_ptr<storage::smb2_proxy::Smb2Proxy::TaskState>,storage::smb2_proxy::Smb2Proxy::PurgeTaskOp::ArgType&,storage::smb2_proxy::Smb2Proxy::PurgeTaskOp::ResultType*,storage::smb2_proxy::Smb2Proxy::DoneCb)’ does not match any template declaration
Smb2Proxy::PurgeTaskOp::Ptr Smb2Proxy::CreateOp<Smb2Proxy::PurgeTaskOp>(
^~~~~~~~~
In file included from /home/workspace/main/util/storage/smb2_proxy/smb2_proxy.cc:5:0:
/home/workspace/main/util/storage/smb2_proxy/smb2_proxy.h:160:20: note: candidate is: template<class Op> typename Op::Ptr storage::smb2_proxy::Smb2Proxy::CreateOp(std::shared_ptr<storage::smb2_proxy::Smb2Proxy::TaskState>, const typename Op::ArgType&, typename Op::ResultType*,storage::smb2_proxy::Smb2Proxy::DoneCb)
typename Op::Ptr CreateOp(std::shared_ptr<TaskState> task_state,
CreateOp -> GetCClassInternal (both are equivalent) The compiler is not able to take specialization of CreateOp and complains that it does not match any declaration. CreateOp-> GetCClassInternal(两者都是等效的)编译器无法对CreateOp进行特殊化,并抱怨它与任何声明都不匹配。
PS: I had another question in which I had made a mistake while posting the code. PS:我还有一个问题,在发布代码时犯了一个错误。 I have deleted the question and am reposting it.
我已删除问题,并正在重新发布。
The problem is that the template parameter T
of GetCClass
(and GetCClassInternal
) is used in non-deduced contexts , it can't be deduced. 问题在于,
GetCClass
(和GetCClassInternal
)的模板参数T
在非推导上下文中使用 ,无法推导。
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
如果模板参数仅在未推导的上下文中使用且未明确指定,则模板参数推导将失败。
1) The nested-name-specifier (everything to the left of the scope resolution operator
::
) of a type that was specified using a qualified-id:1)使用限定ID指定的类型的嵌套名称说明符(范围解析运算符
::
):
You can specify the template argument explicitly. 您可以显式指定模板参数。 eg
例如
auto iptr = test.GetCClass<MyClass::CInt>(i);
auto dptr = test.GetCClass<MyClass::CDouble>(d);
auto sptr = test.GetCClass<MyClass::CStr>(s);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.