能够在C++编译时创建和操作字符串有几个有用的应用程序.尽管可以在C++中创建编译时字符串,但是该过程非常麻烦,因为字符串需要声明为可变字符序列,例如
using str = sequence<'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!'>;
Run Code Online (Sandbox Code Playgroud)
诸如字符串连接,子字符串提取等许多操作可以很容易地实现为对字符序列的操作.是否可以更方便地声明编译时字符串?如果没有,是否有一个提案可以方便地声明编译时字符串?
理想情况下,我们希望能够如下声明编译时字符串:
// Approach 1
using str1 = sequence<"Hello, world!">;
Run Code Online (Sandbox Code Playgroud)
或者,使用用户定义的文字,
// Approach 2
constexpr auto str2 = "Hello, world!"_s;
Run Code Online (Sandbox Code Playgroud)
哪里decltype(str2)有一个constexpr构造函数.方法1的混乱版本可以实现,利用您可以执行以下操作的事实:
template <unsigned Size, const char Array[Size]>
struct foo;
Run Code Online (Sandbox Code Playgroud)
但是,数组需要有外部链接,所以要使方法1起作用,我们必须编写如下内容:
/* Implementation of array to sequence goes here. */
constexpr const char str[] = "Hello, world!";
int main()
{
using s = string<13, str>;
return 0; …Run Code Online (Sandbox Code Playgroud) 是否可以在"现代C++"(C++ 17或更高版本)中将字符串文字作为参数传递给C++模板?
我意识到你可以用构造函数参数做到这一点; 我只是认为将它作为模板参数更方便,而不是深埋在cpp文件中.如果这可能是现代C++的一个新功能,我很好奇.请参阅下面的伪代码我正在尝试做的事情:
伪代码示例:
// Header File /////////////////////////
template<constexpr string Name>
class ModuleBase {
public:
ModuleBase();
string name;
};
class xyz : ModuleBase<"xyz"> {
public:
xyz();
};
// Cpp File //////////////////////////
template<string_literal Name>
ModuleBase<Name>::ModuleBase() {
name = Name;
}
xyz::xyz() : ModuleBase() {
}
Run Code Online (Sandbox Code Playgroud) 我想要一个在其构造函数中包含两个参数的类.第一个可以是int,double或float,所以<typename T>,第二个总是字符串文字"my string",所以我想const char * const.
任何人都可以给我一些可编译的代码,声明一个简单的类模板,并声明该类的对象?
谢谢
是否可以编写一个在编译时将任何 C 字符串文字转换"XY..."为类型的构造?std::integer_sequence<char, 'X', 'Y', ...>我真的想要一个角色包,而不是std::array.
就像是
using MyStringType = magic_const_expr("MyString");
Run Code Online (Sandbox Code Playgroud)
这里演示了一种使用文字运算符的好方法,但不幸的是它需要非标准编译器扩展。
我有以下第三方API:
using StatisticsFunc = double (*)(const std::vector<double> &)
libraryClass::ComputeStatistics(StatisticsFunc sf);
Run Code Online (Sandbox Code Playgroud)
我正在使用这样的:
obj1->ComputeStatistics([](const auto& v) {return histogram("obj1", v);};
obj2->ComputeStatistics([](const auto& v) {return histogram("obj2", v);};
Run Code Online (Sandbox Code Playgroud)
但所有这些lambdas只是重复代码.我宁愿这样:
obj1->ComputeStatistics(getHistogramLambda("obj1"));
Run Code Online (Sandbox Code Playgroud)
所以我需要定义:
constexpr auto getHistogramLambda(const char* name) {
return [](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)
但它不起作用,因为name没有被捕获.这也不会起作用:
constexpr auto getHistogramLambda(const char* name) {
return [name](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)
因为捕获lambda不再是无状态的,不能转换为函数指针.
Ofc可以将其作为宏来实现,但我想要一个现代的C++ 17解决方案.
传递字符串作为模板参数似乎也是一个选项:https:
//stackoverflow.com/a/28209546/7432927,但我很好奇是否有constexpr办法做到这一点.
是否可以在编译时执行唯一的字符串到 int 映射?\n假设我有一个这样的模板用于分析:
\n\ntemplate <int profilingID>\nclass Profile{\npublic:\n Profile(){ /* start timer */ }\n ~Profile(){ /* stop timer */ }\n};\nRun Code Online (Sandbox Code Playgroud)\n\n我将其放在函数调用的开头,如下所示:
\n\nvoid myFunction(){\n Profile<0> profile_me;\n\n /* some computations here */\n}\nRun Code Online (Sandbox Code Playgroud)\n\n现在我正在尝试做类似以下的事情,这是不可能的,因为字符串文字不能用作模板参数:
\n\nvoid myFunction(){\n Profile<"myFunction"> profile_me; // or PROFILE("myFunction")\n\n /* some computations here */\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我可以声明全局变量来解决这个问题,但我认为避免以前的声明会更优雅。表格的简单映射
\n\n就足够了。但到目前为止,无论使用 constexpr、模板元编程还是宏,我都无法找到完成此类映射的方法。有任何想法吗?
\n以下代码片段无法在最新版本的 MSVC (Visual Studio 2022 17.2.2) 上编译。相同的代码片段似乎在以前的编译器版本上运行得很好。
#include <iostream>
#include <format>
template <typename First, typename... Args>
inline auto format1(First&& first, Args&&... args) -> decltype(std::format(first, std::forward<Args>(args)...))
{
return std::format(std::forward<First>(first), std::forward<Args>(args)...);
}
int main()
{
std::cout << format1("hi {} {}", 123, 456);
}
Run Code Online (Sandbox Code Playgroud)
编译器发出以下错误:
1>ConsoleApplication3.cpp(10,24): message : 失败是由于在其生命周期之外读取变量引起的 1>ConsoleApplication3.cpp(10,24): message : 请参阅“first”的用法 1>ConsoleApplication3.cpp( 14): message : 请参阅正在编译的函数模板实例化 'std::string format<const char(&)[9],int,int>(First,int &&,int &&)' 的引用 1>
with 1> [ 1 > 首先=const char (&)[9] 1> ]
似乎以某种方式将字符串文字转发到 std::format 会使编译器认为它们在其生命周期之外使用。我尝试更改该函数以接受const First& first以及各种其他变体,但错误仍然存在。
据我了解,当 …
可能重复:
字符串作为模板参数?
为什么第一个声明可以,但第二个声明没有?为什么std::string不合适?
template <typename T, T x> struct foo { };
using namespace std;
int main()
{
foo<int, 0> f_int; // ok
foo<string, ""> f_string; // not ok
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
error: a non-type template parameter cannot have type 'std::basic_string<char>'
Run Code Online (Sandbox Code Playgroud)
使用clang ++.
出于学术目的,我正在尝试开发一些"文本冒险游戏".我必须自己实现所有数据结构.现在,我在实现通用(模板)LinkedList时遇到了一些问题.
具体来说,这个数据结构适用于所有(原始数据类型和自定义对象)但字符串!(标准库字符串).
当我尝试将字符串添加到列表时,应用程序崩溃并出现以下错误(在控制台中):
"在抛出'std :: logic_error'的实例后调用终止what():basic_string :: _ S_constructor null无效"
该列表使用头节点作为第一个最后一个节点实现为"双链表"
这里的代码("Abstract"List接口):
#ifndef LIST_H_
#define LIST_H_
template <class T>
class List
{
public:
virtual ~List() {}
virtual T get(int position) = 0;
virtual List* add(T item) = 0;
virtual List* insert(T item, int position) = 0;
virtual List* remove(int position) = 0;
virtual int size() const = 0;
virtual bool isEmpty() const = 0;
protected:
private:
};
#endif /* LIST_H_ */
Run Code Online (Sandbox Code Playgroud)
这是LinkedList实现("节点"类):
#include "List.h"
#include <stdlib.h>
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_ …Run Code Online (Sandbox Code Playgroud)