此代码任务 const char[]
并找到最后一个斜杠在哪里:
#include <array>
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
template< int PathIndex, int PathLength >
constexpr const int findlastslash(const char (&path)[PathLength])
{
constexpr const int end = PathLength - PathIndex;
return (PathIndex >= 0 && path[end] != '/' && path[end] != '\\')
? findlastslash< PathIndex - 1, PathLength >( path ) : ( end + 1 );
}
template< int PathLength >
constexpr const int startfindlastslash(const char (&path)[PathLength]) {
return findlastslash< PathLength >( path );
}
int main(int argc, char const *argv[])
{
STATIC_ASSERT( startfindlastslash( "cppdebugger/test_debugger.cpp" ) == 11 );
}
但它不起作用,因为模板递归永远不会停止:
$ g++ -o main.exe --std=c++14 test_debugger.cpp
test_debugger.cpp: In function ‘int main(int, const char**)’:
test_debugger.cpp:2:28: error: static assertion failed: startfindlastslash( "cppdebugger/test_debugger.cpp" ) == 17
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
^
test_debugger.cpp:18:5: note: in expansion of macro ‘STATIC_ASSERT’
STATIC_ASSERT( startfindlastslash( "cppdebugger/test_debugger.cpp" ) == 17 );
^~~~~~~~~~~~~
test_debugger.cpp: In instantiation of ‘constexpr const int findlastslash(const char (&)[PathLength]) [with int PathIndex = -880; int PathLength = 30]’:
test_debugger.cpp:8:114: recursively required from ‘constexpr const int findlastslash(const char (&)[PathLength]) [with int PathIndex = 19; int PathLength = 30]’
test_debugger.cpp:8:114: required from here
test_debugger.cpp:8:114: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
return (PathIndex >= 0 && path[end] != '/' && path[end] != '\\') ? findlastslash< PathIndex - 1, PathLength >( path ) : ( end + 1 );
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
compilation terminated.
我知道可以使用 const char *
轻松做到这一点,但我有兴趣继续使用字符串 "cppdebugger/test_debugger.cpp"
( const char[]
) 作为数组,即不会衰减为 const char *
指针。
更新
更正。模板特化是这样的( < 1, PathLength >
:
template< int PathLength >
constexpr const int findlastslash< 1, PathLength >(const char (&path)[PathLength])
{
constexpr const int end = PathLength;
return ( path[end] != '/' && path[end] != '\\') ? 0 : 1;
}
编译器正确提示的地方:
$ g++ -o main.exe --std=c++14 test_debugger.cpp
test_debugger.cpp:18:82: error: non-class, non-variable partial specialization ‘findlastslash<1, PathLength>’ is not allowed
constexpr const int findlastslash< 1, PathLength >(const char (&path)[PathLength])
^
test_debugger.cpp: In function ‘int main(int, const char**)’:
test_debugger.cpp:2:28: error: static assertion failed: startfindlastslash( "cppdebugger/test_debugger.cpp" ) == 11
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
^
test_debugger.cpp:26:5: note: in expansion of macro ‘STATIC_ASSERT’
STATIC_ASSERT( startfindlastslash( "cppdebugger/test_debugger.cpp" ) == 11 );
^~~~~~~~~~~~~
test_debugger.cpp: In instantiation of ‘constexpr const int findlastslash(const char (&)[PathLength]) [with int PathIndex = -880; int PathLength = 30]’:
test_debugger.cpp:9:56: recursively required from ‘constexpr const int findlastslash(const char (&)[PathLength]) [with int PathIndex = 19; int PathLength = 30]’
test_debugger.cpp:9:56: required from here
test_debugger.cpp:9:56: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
? findlastslash< PathIndex - 1, PathLength >( path ) : ( end + 1 );
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
compilation terminated.
相关问题:
最佳答案
如果你在 C++14 中,你不再需要 constexpr
的递归,你可以使用常规循环:
template<std::size_t PathLength>
constexpr const int findlastslash(const char (&path)[PathLength])
{
for (std::size_t i = PathLength; i != 0; --i) {
if (path[i - 1] == '/' || path[i - 1] == '\\') {
return i;
}
}
return 0;
}
在 C++11 中,你可能会这样做:
template<std::size_t PathLength>
constexpr const int findlastslash(const char (&path)[PathLength], std::size_t i = PathLength)
{
return (i == 0)
? 0
: ((path[i - 1] == '/' || path[i - 1] == '\\')
? i
: findlastslash(path, i - 1));
}
C++17 中的 constexpr 版本(去除常规参数 i
):
template<std::size_t PathLength, std::size_t I = PathLength>
constexpr const int findlastslash(const char (&path)[PathLength])
{
if constexpr (I == 0) {
return 0;
} else {
if (path[I - 1] == '/' || path[I - 1] == '\\') {
return I;
}
return findlastslash<PathLength, I - 1>(path);
}
}
在 C++17 之前,您必须使用特化或重载来代替 if constexpr
,但函数不能部分特化。
所以结构特化可能是:
template <std::size_t I> struct findlastslash_impl
{
template <std::size_t PathLength>
constexpr const int findlastslash(const char (&path)[PathLength])
{
if (path[I - 1] == '/' || path[I - 1] == '\\') {
return I;
}
return findlastslash_impl<I - 1>()(path);
}
}
template<> struct findlastslash_impl<0>
{
template<std::size_t PathLength>
constexpr const int findlastslash(const char (&)[PathLength])
{
return 0;
}
};
template<std::size_t PathLength>
constexpr const int findlastslash(const char (&path)[PathLength])
{
return findlastslash_impl<PathLength>()(path);
}
或重载:
template <std::size_t PathLength>
constexpr const int findlastslash_impl(std::integral_constant<std::size_t, 0>,
const char (&path)[PathLength])
{
return 0;
}
template <std::size_t PathLength, std::size_t I>
constexpr const int findlastslash_impl(std::integral_constant<std::size_t, I>,
const char (&path)[PathLength])
{
if (path[I - 1] == '/' || path[I - 1] == '\\') {
return I;
}
return findlastslash_impl(std::integral_constant<std::size_t, I - 1>(), path);
}
template<std::size_t PathLength>
constexpr const int findlastslash(const char (&path)[PathLength])
{
return findlastslash_impl(std::integral_constant<std::size_t, PathLength>(), path);
}
关于c++ - 使用参数推导时如何停止模板递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59472892/