如何让编译器在指针上选择模板的静态数组版本

How to have compiler choose static array version of template over pointer?

本文关键字:静态 版本 数组 选择 编译器 指针      更新时间:2023-10-16

我正在尝试做一些接近于此的事情:

template<typename TChar, size_t TSize>
inline size_t StringLength(TChar(&)[TSize])
{
    return TSize - 1;
}
template<typename TChar>
inline size_t StringLength(const TChar* value)
{
    return std::char_traits<TChar>::length(value);
}

。但是当调用 StringLength("abc") 时,编译器发现它不明确:

test.cpp(15): could be 'size_t StringLength<char>(const TChar *const )'
with
[
    TChar=char
]
test.cpp(9): or       'size_t StringLength<const char,4>(TChar (&)[4])'
with
[
    TChar=const char
]
while trying to match the argument list '(const char [4])'

(此测试在VS2013中完成。

我只是想在尺寸可用时避免使用strlen。有没有办法做到这一点,或者比我正在尝试的更好的选择?

只需通过 const 引用获取指针,这会阻止模板参数推导期间数组到指针的转换:

template<typename TChar>
inline size_t StringLength(const TChar* const & value)
                                      //^^^^^^^
{
    return std::char_traits<TChar>::length(value);
}

演示。

这种方式有效:

#include <cstddef>
#include <iostream>
#include <string>
#include <type_traits>
template<typename TChar, std::size_t TSize>
inline std::size_t StringLength(TChar(&)[TSize])
{
  return TSize;
}
template<typename TCharArray>                   // v-- using SFINAE to disable this overload if TCharArray is not an array type
inline std::size_t StringLength(TCharArray value, typename std::enable_if<!std::is_array<TCharArray>::value, void>::type * = nullptr)
{
  return std::char_traits<typename std::remove_pointer<TCharArray>::type>::length(value);
}

int main() {
  std::cout << StringLength("foo") << "n";
  char const *ptr = "foo";
  std::cout << StringLength(ptr) << "n";
}

。但是你确定这是一个好主意吗?我知道你想避免这个讨论,但它是...硬。我的意思是,考虑

char str[100] = "foo";
std::cout << StringLength(str); // will give 100.

它并不完全符合 POLA 标准。