4
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;
}

clang:

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

Compile error:

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

This code compiled in g++ 5.4(linux)

How can I fix this.

Constructor
  • 7,273
  • 2
  • 24
  • 66
ryancheung
  • 2,999
  • 3
  • 24
  • 25
  • after remove `template<>` from the second definition, it raise `error: no matching function for call to 'CheckIntMap'` @C – ryancheung Dec 22 '17 at 08:35
  • 1
    I removed my earlier comment because it was wrong (sorry): you *can* specialize function templates, but it might not be recommended to do so as it can interact with overload resolution in a weird way if you also overload it, and overloading is more common (cf http://www.gotw.ca/publications/mill17.htm ). The error you got after removing template<> (and turning a specialization into an overload) was certainly because you didn't declare the second overload before using it in the first. Your problem is solved, but I thought I'd add some additional explanations. – Caninonos Dec 22 '17 at 08:47

1 Answers1

4

You could move the declaration of the specialization before where the implicit instantiation is required. e.g.

// 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;
}
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Thank you so much, it fix the compiling after placing declarations before definitions. – ryancheung Dec 22 '17 at 08:37
  • By the way, Isn't this standard to defining template functions? Place declarations before definitions, which isn't for normal functions. – ryancheung Dec 22 '17 at 08:45
  • 1
    @ryancheung Specialization and instantiation are special for templates, but the basic idea is same; when you want to call a function (for this case it's the specialization) it should be declared before. – songyuanyao Dec 22 '17 at 08:49