函数模板不适用于字符串文本
Function template won't work with string literals
背景:
我正在研究一个查询 DSL,它将解析具有 ==
、<
等的表达式,并通过运算符重载返回过滤器对象。
问题:
我的模板方法在与字符串文本一起使用时失败。我尝试提供模板的特定实例,同时采用std::string
和char
但似乎都不起作用。
代码如下。导致 main 中问题的行标有注释。我尝试过的替代解决方案在代码中被注释掉了。
可以在此处找到相同代码的可运行 repl。
我确实知道用 std::string("text")
手动包装字符串文字是可行的,但如果可能的话,我希望能够使用纯字符串文字。
#include <iostream>
template<typename T>
struct Filter;
struct Field
{
Field(const std::string &val): name(val) { }
Field(std::string &&val): name(std::move(val)) { }
std::string name;
// template <signed N>
// Filter<std::string> operator==(const char (&val) [N]);
template <typename T>
Filter<T> operator==(const T &val);
};
template <typename T>
Filter<T> Field::operator==(const T &val)
{
return Filter<T>{ *this, val, "==" };
}
// template <signed N>
// Filter<std::string> Field::operator==(const char (&val) [N])
// {
// return Filter<std::string>{ *this, std::string(val), "==" };
// }
// template <>
// Filter<std::string> Field::operator==<std::string>(const std::string &val)
// {
// return Filter<std::string>{ *this, val, "==" };
// }
template<typename T>
struct Filter
{
Field f;
T val;
std::string op;
};
int main() {
Field f1 { "field1" };
Field f2 { "field1" };
std::cout << (f1 == 1).val;
std::cout << (f1 == "Hello").val; // <--- the source of my problems
}
问题是 c 数组不可复制,所以
Filter<char [6]>{ *this, val, "==" }; // Error
您的重载是正确的,但Filter
需要在operator==
重载之前重新排序和定义。重载返回Filter<T>
依赖于T
,所以在这种情况下Filter
的定义可以推迟。但是当你返回Filter<std::string>
编译器需要预先Filter
的实际定义。
#include <iostream>
template<typename T>
struct Filter;
struct Field
{
Field(const std::string &val): name(val) { }
Field(std::string &&val): name(std::move(val)) { }
std::string name;
template <std::size_t N> Filter<std::string> operator==(const char (&val) [N]);
template <typename T>
Filter<T> operator==(const T &val);
};
template<typename T>
struct Filter
{
Field f;
T val;
std::string op;
};
template <typename T>
Filter<T> Field::operator==(const T &val)
{
return Filter<T>{ *this, val, "==" };
}
template <std::size_t N>
Filter<std::string> Field::operator==(const char (&val) [N])
{
return Filter<std::string>{ *this, std::string(val), "==" };
}
int main() {
Field f1 { "field1" };
Field f2 { "field1" };
std::cout << (f1 == 1).val;
std::cout << (f1 == "Hello").val;
}
演示
您可以做的是专门针对T
被推导出为char[N]
的情况进行Filter
。 添加
template<std::size_t N>
struct Filter<char[N]>
{
Field f;
std::string val;
std::string op;
};
将导致Filter<T>{ *this, val, "==" }
调用上述专用化,它将使用std::string
来存储val
。
由于您有 C++17 标签,这里有另一种解决此问题的选项: 演绎指南
#include <iostream>
template<typename T>
struct Filter;
struct Field
{
Field(const std::string &val): name(val) { }
Field(std::string &&val): name(std::move(val)) { }
std::string name;
// note the use of auto here
template <typename T>
auto operator==(const T &val);
};
template <typename T>
auto Field::operator==(const T &val)
{
// do not use Filter<T> here, or the deduction guide won't kick in
return Filter{ *this, val, "==" };
}
template<typename T>
struct Filter
{
Field f;
T val;
std::string op;
};
// ------- Deduction Guides -----------
template<typename T>
Filter(Field, T, std::string) -> Filter<T>;
// will tell the compiler to create a Filter<string> with a c-array argument
template<std::size_t N>
Filter(Field, const char(&)[N], std::string) -> Filter<std::string>;
// ------------------------------------
int main() {
Field f1 { "field1" };
Field f2 { "field1" };
std::cout << (f1 == 1).val;
// creates a Filter<string> instead of trying to
// create a Filter<const char(&)[6]> due to the deduction guide
std::cout << (f1 == "Hello").val;
}
相关文章:
- 在 C++ 中从 8 位 ASCII 字符创建 7 位 ASCII 文本字符串
- cin>>gender 和 cin>>*gender ( c 样式文本字符串)有什么区别
- 是否可以动态检查文本字符串是否是 C++ 中给定类的成员?
- 用Zlib解压缩文本字符串
- 将文本字符串作为常量字符 * 参数传递会导致代码分析器错误
- 来自文本字符串或某种其他机制的代码类自动生成器
- 函数读取最大和min int值,并用文本字符串返回
- 模板代码和文本字符串
- 声明具有常量引用与常量变量的常量文本字符串
- 加密给定的文本字符串-Caesar Cipher
- 如何使用键盘输入和sf ::文本在SFML中添加一种文本框以显示文本字符串
- 在C++代码中,如何让用户在2个文本字符串之间输入一个数字
- 如何将文本从一个文件复制到另一个文件,然后将文本字符串的第一个字母转换为大写
- 从文本字符串推断类型
- 跟踪内存中的文本字符串
- 将字符串变量与整数和文本字符串连接起来的 C++ 字符串流
- 将 char 数组分配给文本字符串 - C++
- 如何修复将文本字符串附加到 C 字符串的错误
- 使用C++读取不同长度的多个文本字符串
- 在C++中创建原始文本字符串,类似于 C# 的"@ string"