【问题标题】:explicit specialization of 'CheckIntMap<>' after instantiation实例化后“CheckIntMap<>”的显式特化
【发布时间】:2017-12-22 08:29:56
【问题描述】:
template<typename... U> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1, U&&... u)
{
    return (CheckIntMap(szStr, nDefaultInt, szOptStr1, nOptInt1) == nOptInt1) ? nOptInt1 : CheckIntMap(szStr, nDefaultInt, std::forward<U>(u)...);
}

template<> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1)
{
    return CompareUTF8(szStr, szOptStr1) ? nOptInt1 : nDefaultInt;
}

叮当声:

Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Found CUDA installation: /usr/local/cuda, version 7.0

编译错误:

/Users/xxx/xxx/xxxx/common/src/constexprfunc.hpp:58:30: error: explicit specialization of 'CheckIntMap<>' after instantiation
    template<> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1)
                             ^
/Users/xxx/xxx/xxxx/common/src/constexprfunc.hpp:55:17: note: implicit instantiation first required here
        return (CheckIntMap(szStr, nDefaultInt, szOptStr1, nOptInt1) == nOptInt1) ? nOptInt1 : CheckIntMap(szStr, nDefaultInt, std::forward<U>(u)...);

此代码在 g++ 5.4(linux) 中编译

我该如何解决这个问题。

【问题讨论】:

  • 从第二个定义中删除template&lt;&gt;后,它会提升error: no matching function for call to 'CheckIntMap'@C
  • 我删除了我之前的评论,因为它是错误的(抱歉):您可以专门化函数模板,但可能不建议这样做,因为它可以与重载解析交互如果你也重载它,以一种奇怪的方式,并且重载更常见(参见gotw.ca/publications/mill17.htm)。删除 template (并将特化变为重载)后出现的错误肯定是因为您在第一次使用它之前没有声明第二个重载。您的问题已解决,但我想我会添加一些额外的解释。

标签: c++ templates template-specialization explicit-specialization


【解决方案1】:

您可以将特化的声明移到需要隐式实例化的位置之前。例如

// declarations
template<typename... U> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1, U&&... u);
template<> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1);

// definitions
template<typename... U> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1, U&&... u)
{
    return (CheckIntMap(szStr, nDefaultInt, szOptStr1, nOptInt1) == nOptInt1) ? nOptInt1 : CheckIntMap(szStr, nDefaultInt, std::forward<U>(u)...);
}

template<> constexpr int CheckIntMap(const char *szStr, int nDefaultInt, const char *szOptStr1, int nOptInt1)
{
    return CompareUTF8(szStr, szOptStr1) ? nOptInt1 : nDefaultInt;
}

【讨论】:

  • 非常感谢,它修复了在定义之前放置声明后的编译。
  • 对了,这不是定义模板函数的标准吗?将声明放在定义之前,这不适用于普通函数。
  • @ryancheung 特化和实例化是模板特有的,但基本思想是一样的;当你想调用一个函数时(在这种情况下它是特化)它应该在之前声明。
猜你喜欢
  • 2011-12-08
  • 2012-09-25
  • 1970-01-01
  • 2019-04-15
  • 2020-11-16
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
相关资源
最近更新 更多