【问题标题】:explicit template specialization from function template not working来自函数模板的显式模板特化不起作用
【发布时间】:2019-09-13 04:51:17
【问题描述】:

我正在尝试对从另一个模板函数调用的模板函数进行显式特化。以下是一个最小的非工作示例,我正在尝试实现以下想法:

CIntCDoubleCStr 相当于我需要执行的操作。但是,CStr 构造函数需要一些不同的格式。 MyClass 相当于一个工厂,当被请求时,它将返回 CIntCDoubleCStr 的实例之一。

这种结构的动机:假设 GetCClass 函数是从大约 100 行的函数中调用的,只有一个区别:类的类型。从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;
}

我收到以下错误:

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

我已阅读多个答案,但我不明白为什么这不起作用。任何帮助表示赞赏。

编辑: 我无法理解,但在我的实际代码中,我在本地得到以下信息:

/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(两者是等价的) 编译器无法对 CreateOp 进行专门化,并抱怨它与任何声明都不匹配。

PS:我还有一个问题,我在发布代码时犯了一个错误。我已删除问题并重新发布。

【问题讨论】:

    标签: c++ templates c++14


    【解决方案1】:

    问题是GetCClass(和GetCClassInternal)的模板参数Tnon-deduced contexts中使用,无法推导出来。

    如果模板参数仅用于非推导上下文且未明确指定,则模板参数推导失败。

    1) 使用限定 ID 指定的类型的嵌套名称说明符(范围解析运算符 :: 左侧的所有内容):

    您可以明确指定模板参数。例如

    auto iptr = test.GetCClass<MyClass::CInt>(i);
    auto dptr = test.GetCClass<MyClass::CDouble>(d);
    auto sptr = test.GetCClass<MyClass::CStr>(s);
    

    LIVE

    【讨论】:

    • 你能看看编辑吗?我仍然无法弄清楚我的内部设置有什么问题。我已经合并了你的 cmets,但是编译器仍然抱怨它找不到模板声明。
    • @AmanDeepGautam 抱歉,如果没有足够的信息,我无法帮助您。 MCVE 可能会有所帮助,我建议发布一个新问题,因为它似乎是一个新问题。
    • 问题是我无法创建 MCVE。让我看看我能不能得到它。如果需要,将发布一个新问题。
    猜你喜欢
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 2019-04-15
    相关资源
    最近更新 更多