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