在将 std::string 分配给模板参数期间编译时出错

Posted

技术标签:

【中文标题】在将 std::string 分配给模板参数期间编译时出错【英文标题】:Error at compile time during assignment of a std::string to template parameter 【发布时间】:2017-10-10 13:26:39 【问题描述】:

我在 Visual Studio 2013 中使用 C++ 11。这是我的上下文:我想调用模板方法:

template<typename T> bool InvokeMyMethod(std::string methodName, T &retValue, int  modeType...)

并将模板参数作为返回值传递。这样,我将使用整数、浮点数、std::string 参数调用此函数。 但是,当我尝试将 std::string 分配给模板参数时,出现错误。这是我的头文件和实现代码:

// include files ...

int  IncValue(int iParam)

return ++iParam;

float DivValue(float fParam)

return (fParam / 2);

const char* GetHello()

return "Hello\n";


template<typename T> bool InvokeMyMethod(std::string methodName, T &retValue, int  modeType...)

bool bRet = false;
switch (modeType)

case 0:  // basic

std::cout << " Method " << methodName << " correctly invoked ." << std::endl;
bRet = true;

break;
case 1:  //call int function

va_list args;
va_start(args, modeType);
int iParam = va_arg(args, int);
int result = IncValue(iParam);
va_end(args);
retValue = result;
bRet = true;

break;

case 2:   // call float function

va_list args;
va_start(args, modeType);
float fParam = (float)va_arg(args, double);
float result = DivValue(fParam);
va_end(args);
retValue = result;
bRet = true;

break;

case 3:  //call string function

    const char *strReturn = GetHello();
    std::string sValReturned;
    sValReturned = strReturn;
    std::cout << " Template for string : " << typeid(T).name() << std::endl;

//HERE IS MY PROBLEM AT COMPILE TIME
retValue = sValReturned;  // if i comment this line, everything is  
                          // ok, otherwise i got compiling error            
                          // like: error C2440: '=' : cannot convert 
                          // from 'std::string' to 'int' 
                          // AND
                          // cannot convert from 'std::string' to 
                          // 'float'
    bRet = true;

break;

return bRet;

//**************** CPP : 主要 *****************

// include files ...

int main()

std::string strMethod = "";
strMethod = "Method_A";
int iResult = 0;
int iParam = 10;
if (InvokeMyMethod(strMethod, iResult, 1,iParam))

    std::cout << " Invoke  Method " << strMethod << "  returns : " << iResult << std::endl;

else

    std::cout << " Error : Invoke Method " << strMethod << ". Method or Class not found!" << std::endl;


strMethod = "Method_B";
float fResult = 0;
float fParam = 9.0f;
if (InvokeMyMethod(strMethod, fResult, 2, fParam))

    std::cout << " Invoke  Method " << strMethod << "  returns : " << fResult << std::endl;

else

    std::cout << " Error : Invoke  Method " << strMethod << ". Method or Class not found!" << std::endl;


strMethod = "Method_C";
std::string sResult ="";
std::string sParam = "Hello";
if (InvokeMyMethod(strMethod, sResult, 3, sParam))

    std::cout << " Invoke  Method " << strMethod << "  returns : " << sResult << std::endl;

else

    std::cout << " Error : Invoke  Method " << strMethod << ". Method or Class not found!" << std::endl;



std::cout << "Press any key...";
std::cin.get();
return 0;

当我尝试(在 .h 文件中,在模板方法中)将字符串值分配给模板参数时,出现以下错误。

错误 C2440:“=”:无法从“std::string”转换为“int”

无法从 'std::string' 转换为 'float'

我该如何解决这个问题?

【问题讨论】:

尝试 InvokeMyMethod<:string>()。您没有提供模板类型。 函数模板在实例化时必须对其进行完整的类型检查——也就是说,无论T 碰巧是什么类型,您的所有开关案例都必须同时正确。运行时类型切换和模板不能混用。 由于 InvokeMyMethod 实际上是四个完全独立的函数,并且您通过 modeType 选择其中一个,您可能可以将该决定从函数中移出并编写四个不同的重载。 【参考方案1】:

尝试以这种方式使用模板特化:

template<typename T>
bool InvokeMyMethod(std::string methodName, T &retValue, int  modeType...)

    bool bRet = false;
    switch (modeType)
    
    case 0:  // basic
    
        std::cout << " Method " << methodName << " correctly invoked ." << std::endl;
        bRet = true;
    
        break;
    case 1:  //call int function
    
        va_list args;
        va_start(args, modeType);
        int iParam = va_arg(args, int);
        int result = IncValue(iParam);
        va_end(args);
        retValue = result;
        bRet = true;
    
        break;

    case 2:   // call float function
    
        va_list args;
        va_start(args, modeType);
        float fParam = (float)va_arg(args, double);
        float result = DivValue(fParam);
        va_end(args);
        retValue = result;
        bRet = true;
    
        break;

    
    return bRet;


template<>
bool InvokeMyMethod(std::string methodName, std::string &retValue, int  modeType...) 
    bool bRet = false;
    const char *strReturn = GetHello();
    std::string sValReturned;
    sValReturned = strReturn;

    retValue = sValReturned;

    bRet = true;
    return bRet;

【讨论】:

您好 Danilo,感谢您的回答。有用!伟大的!但是……我之前的代码有什么问题? 您好,很高兴我的回答对您有所帮助。我相信问题在于使用 C++ 模板,而没有对非本地类型(如 int、float、double ......)使用模板专门化。事实上,在同一个函数中,您将 retValue 分配给了不同的类型(本机和复杂),并且这个“类型推断”问题仅针对复杂类型 (std::string) 分配提出。

以上是关于在将 std::string 分配给模板参数期间编译时出错的主要内容,如果未能解决你的问题,请参考以下文章

传递给 std::basic_string 的分配器能否将其方法设为虚拟

模板typedef与std :: vector有自定义分配器

切换基于模板类型 C++ 的引用参数传递

复制分配期间的c ++字符串容量更改

我可以将 std::string 传递给 DLL 吗?

将字符串*分配给char * c ++ [关闭]