简体   繁体   中英

Function template specialization in MacOSX with clang

I am porting some codes from Windows to MacOSX. There is a problem about Function template specialization. I was successfully compile this file in Windows with msvc14.0 and clang5.0.

#include <cstring>
#include <string>

#include <iostream>

template<typename CHAR_TYPE>
size_t string_length(CHAR_TYPE text)
{
    static_assert(false, "string_length is not supported this type.");
    return 0;
}

template<typename CHAR_TYPE>
size_t string_length(const std::basic_string<CHAR_TYPE>& text)
{
    return text.size();
}

template<>
inline size_t string_length(const char* szText)
{
    return strlen(szText);
}

template<>
inline size_t string_length(const wchar_t* szwText)
{
    return wcslen(szwText);
}

int main()
{
    std::cout << "SZ length " << string_length("IIII") << std::endl;
    std::cout << "WSZ length " << string_length(L"IIII") << std::endl;
    std::cout << "string length " << string_length(std::string("IIII")) << std::endl;
    std::cout << "wstring length " << string_length(std::wstring(L"IIII")) << std::endl;
}

When I compile it in MacOSX with clang5.0, I got a error:

clang_test.cpp:9:5: error: static_assert failed "string_length is not supported
      this type."
    static_assert(false, "string_length is not supported this type.");
    ^             ~~~~~
1 error generated.

When I Remove the first function:

template<typename CHAR_TYPE>
size_t string_length(CHAR_TYPE text)
{
    static_assert(false, "string_length is not supported this type.");
    return 0;
}

I got some other errors:

clang_test.cpp:19:15: error: no function template matches function template
      specialization 'string_length'
inline size_t string_length(const char* szText)
              ^
clang_test.cpp:13:8: note: candidate template ignored: could not match 'const
      basic_string<type-parameter-0-0, char_traits<type-parameter-0-0>,
      allocator<type-parameter-0-0> > &' against 'const char *'
size_t string_length(const std::basic_string<CHAR_TYPE>& text)
       ^
clang_test.cpp:25:15: error: no function template matches function template
      specialization 'string_length'
inline size_t string_length(const wchar_t* szwText)
              ^
clang_test.cpp:13:8: note: candidate template ignored: could not match 'const
      basic_string<type-parameter-0-0, char_traits<type-parameter-0-0>,
      allocator<type-parameter-0-0> > &' against 'const wchar_t *'
size_t string_length(const std::basic_string<CHAR_TYPE>& text)
       ^
clang_test.cpp:33:34: error: no matching function for call to 'string_length'
    std::cout << "SZ length " << string_length("IIII") << std::endl;
                                 ^~~~~~~~~~~~~
clang_test.cpp:13:8: note: candidate template ignored: could not match
      'basic_string<type-parameter-0-0, char_traits<type-parameter-0-0>,
      allocator<type-parameter-0-0> >' against 'char const[5]'
size_t string_length(const std::basic_string<CHAR_TYPE>& text)
       ^
clang_test.cpp:34:35: error: no matching function for call to 'string_length'
    std::cout << "WSZ length " << string_length(L"IIII") << std::endl;
                                  ^~~~~~~~~~~~~
clang_test.cpp:13:8: note: candidate template ignored: could not match
      'basic_string<type-parameter-0-0, char_traits<type-parameter-0-0>,
      allocator<type-parameter-0-0> >' against 'wchar_t const[5]'
size_t string_length(const std::basic_string<CHAR_TYPE>& text)
       ^
4 errors generated.

What is the problem?

Following is indeed wrong even if function is not instantiated:

template<typename CHAR_TYPE>
size_t string_length(CHAR_TYPE text)
{
    static_assert(false, "string_length is not supported this type.");
    return 0;
}

temp.res/8 :

The program is ill-formed, no diagnostic required, if:

  • If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.
  • [..]
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or
  • [..]

You may use instead (and use overload instead of specialization for const char* , const wchar_t* ):

template<typename CHAR_TYPE>
size_t string_length(CHAR_TYPE text) = delete;

If you prefer to keep the static_assert , you have to create an helper:

template <typename T> struct always_false : false_type {};

template<typename CHAR_TYPE>
size_t string_length(CHAR_TYPE text)
{
    static_assert(always_false<CHAR_TYPE>::value,
                  "string_length is not supported this type.");
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM