(C++) error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
(C++) error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
我正在尝试编写一个函数,该函数将 return 来自给定开始和结束索引的子字符串。这是我写的代码,但是当我 运行 它给了我错误。我正在使用 gtest 运行 它不是 main()。
template <typename S>
S substring(S string_, int Istart, int Iend)
{
S substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
这是我得到的错误:
In file included from test.cpp:2:0:
lab2.cpp: In instantiation of ‘S substring(S, int, int) [with S = const char*]’:
test.cpp:56:1: required from here
lab2.cpp:91:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
S substr = string_[Istart];
~~~~~~~^
我的测试代码是这样的:
TEST(subStr, T1){
string str="he";
EXPECT_EQ(str,substring("hello", 0, 2));
}
TEST(subStr, T2){
string str="urge";
EXPECT_EQ(str,substring("hamburger", 4, 8));
}
假设预期的类型是 string
。 +=
运算符存在于 string
类型。
一个简单的解决方法是替换
S substr = string_[Istart];
和
S substr;
substr += string_[Istart];
这不适用于 const char*
类型
以下适用于 string
和 const char*
。
#include <exception>
#include <iostream>
#include <functional>
#include <string>
#include <type_traits>
template <typename S>
S substring(S string_, int Istart, int Iend)
{
if constexpr (std::is_same_v<S, std::string>) {
if(Istart < Iend){
return string_.substr(Istart, Iend-Istart);
}
}
else if constexpr (std::is_same_v<S, const char*>)
{
if(Istart < Iend){
std::string temp = std::string(string_);
return (temp.substr(Istart, Iend-Istart)).c_str();
}
}
else throw;
}
对于给定的调用上下文,这:
EXPECT_EQ(str,substring("hello", 0, 2));
利用
的扩展
substring<const char*>
因此生成的代码变为:
const char* substring(const char* string_, int Istart, int Iend)
{
const char* substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
显然这行不通。 const char* substr = string_[Istart];
正在从 char
初始化 const char *
。正如我所见,您有两种选择,但只有一种选择是遥不可及的。由于 EXPECT_EQ
测试等价性,因此无论如何 走指针路线都行不通 。您需要在该测试的至少一侧有一个可比较的 std::string
guaranteed,并且在仍然提供您的表达论据的同时保证的唯一方法是这样的:
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
这会将与 std::string
兼容的任何内容作为源参数。结果总是 std::string
,然后可以将其用于与各种事物进行比较,包括 char[N]
、const char *
,当然还有 std::string
.
它仍然有一个巨大的警告,即必须订购 Istart
和 Iend
。消除这种脆弱性正是 std::string
的标准库 substr
成员不使用 begin,end 的原因;它需要一个开始,长度。尽管如此,这很容易是做你想做的事情的最简单的方法。(尽管如此,单行的性质表明这种事情非常有用)。
例子
我没有 GoogleTest,但一个简单的断言宏将演示针对 std::string
的不同比较的测试是否有效:
#include <iostream>
#include <string>
#include <cassert>
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
int main()
{
const char *kvalptr = "welcome";
std::string kvalstr = kvalptr;
auto res = substring("abdwelcomedef", 3, 10);
// test that both lhs prospects test against our result
assert(kvalptr == res);
assert(kvalstr == res);
// output res and one of the prospects.
std::cout << res << '\n' << kvalptr << '\n';
}
输出
welcome
welcome
我正在尝试编写一个函数,该函数将 return 来自给定开始和结束索引的子字符串。这是我写的代码,但是当我 运行 它给了我错误。我正在使用 gtest 运行 它不是 main()。
template <typename S>
S substring(S string_, int Istart, int Iend)
{
S substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
这是我得到的错误:
In file included from test.cpp:2:0:
lab2.cpp: In instantiation of ‘S substring(S, int, int) [with S = const char*]’:
test.cpp:56:1: required from here
lab2.cpp:91:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
S substr = string_[Istart];
~~~~~~~^
我的测试代码是这样的:
TEST(subStr, T1){
string str="he";
EXPECT_EQ(str,substring("hello", 0, 2));
}
TEST(subStr, T2){
string str="urge";
EXPECT_EQ(str,substring("hamburger", 4, 8));
}
假设预期的类型是 string
。 +=
运算符存在于 string
类型。
一个简单的解决方法是替换
S substr = string_[Istart];
和
S substr;
substr += string_[Istart];
这不适用于 const char*
类型
以下适用于 string
和 const char*
。
#include <exception>
#include <iostream>
#include <functional>
#include <string>
#include <type_traits>
template <typename S>
S substring(S string_, int Istart, int Iend)
{
if constexpr (std::is_same_v<S, std::string>) {
if(Istart < Iend){
return string_.substr(Istart, Iend-Istart);
}
}
else if constexpr (std::is_same_v<S, const char*>)
{
if(Istart < Iend){
std::string temp = std::string(string_);
return (temp.substr(Istart, Iend-Istart)).c_str();
}
}
else throw;
}
对于给定的调用上下文,这:
EXPECT_EQ(str,substring("hello", 0, 2));
利用
的扩展substring<const char*>
因此生成的代码变为:
const char* substring(const char* string_, int Istart, int Iend)
{
const char* substr = string_[Istart];
for(int i=(Istart+1); i<Iend; i++)
{
substr += string_[i];
}
return substr;
}
显然这行不通。 const char* substr = string_[Istart];
正在从 char
初始化 const char *
。正如我所见,您有两种选择,但只有一种选择是遥不可及的。由于 EXPECT_EQ
测试等价性,因此无论如何 走指针路线都行不通 。您需要在该测试的至少一侧有一个可比较的 std::string
guaranteed,并且在仍然提供您的表达论据的同时保证的唯一方法是这样的:
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
这会将与 std::string
兼容的任何内容作为源参数。结果总是 std::string
,然后可以将其用于与各种事物进行比较,包括 char[N]
、const char *
,当然还有 std::string
.
它仍然有一个巨大的警告,即必须订购 Istart
和 Iend
。消除这种脆弱性正是 std::string
的标准库 substr
成员不使用 begin,end 的原因;它需要一个开始,长度。尽管如此,这很容易是做你想做的事情的最简单的方法。(尽管如此,单行的性质表明这种事情非常有用)。
例子
我没有 GoogleTest,但一个简单的断言宏将演示针对 std::string
的不同比较的测试是否有效:
#include <iostream>
#include <string>
#include <cassert>
template<class S>
std::string substring(S s, int Istart, int Iend)
{
return std::string(s).substr(Istart, Iend - Istart);
}
int main()
{
const char *kvalptr = "welcome";
std::string kvalstr = kvalptr;
auto res = substring("abdwelcomedef", 3, 10);
// test that both lhs prospects test against our result
assert(kvalptr == res);
assert(kvalstr == res);
// output res and one of the prospects.
std::cout << res << '\n' << kvalptr << '\n';
}
输出
welcome
welcome