c++ - 使用参数推导时如何停止模板递归?
问题描述
此代码任务 aconst 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 *
,但我有兴趣继续使用 string "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++17 中的std::string_view中可用。
见:std::basic_string_view::rfind
#include <string_view>
using namespace std::literals;
int main()
{
static_assert("cppdebugger/test_debugger.cpp"sv.rfind('/') == 11);
static_assert("cppdebugger/test_debugger.cpp"sv.find_last_of("\\/"sv) == 11);
}
推荐阅读
- javascript - 尝试使用下拉列表创建多个动画烤肉串菜单在 Laravel 8 中不起作用
- pandas - 如何通过 pandas 从 OHLC 数据中获得前 15 分钟的高点?
- php - 如何在不删除括号内容的情况下替换方括号
- python - 在 Python 中用给定语言说单词
- c# - Ironpython 中没有名为 importlib 的模块错误
- java - 如果测试超时,有没有办法从 JUnit5 获取回调?
- javascript - 如何在咖啡脚本中包含 jquery 插件
- jquery - 谷歌表单选项输入与引导表单链接
- c++ - LLVM STLExtras 中的错误:使用 GCC11 的“const”之前的预期 unqualified-id
- c - 尝试使用命令提示符在 c 中运行简单的图形程序