c++templatestemplate-specializationexplicit-specialization

explicit specialization of 'CheckIntMap<>' after instantiation


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.


Solution

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