(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* 类型

以下适用于 stringconst 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.

它仍然有一个巨大的警告,即必须订购 IstartIend。消除这种脆弱性正是 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