Lars Kakavandi-Nielsen
Lars Kakavandi-Nielsen

Reputation: 2188

Invalid binary expression operands for template argument for special string case

Here is what I wanted to achive. I need a function that takes lhs and rhs where lhs is always of type std::string and return the string {rhs} + {lhs}. In theory rhs can be any type, but the library will only take std::string and all types supported by std::to_string(input).

So my idea was to use std::is_same<T1, T2>::value to identify if rhs is a std::string. Using a structure similar to this:

#include <string>
#include <cstdint>
#include <iostream>

#include <type_traits>

template<typename T> std::string test(std::string lhs, T rhs)
{

    std::string base = lhs + " = "; 
    if (std::is_same<T, std::string>::value)
    {
        return base + rhs;
    }
    else
    {
        return lhs + " = " + std::to_string(rhs);  
    }
}

int main(void)
{
    std::string a = "12"; 
    int b = 10;

    std::cout << test(a, b) << "\n"; 

    uint8_t c = 253;
    std::cout << test(a, c) << "\n";

    std::string d = "15";
    std::cout << test(a, d) << "\n"; 
}

But I get this error when trying to compile:

main.cpp:13:21: error: invalid operands to binary expression ('std::string' (aka 'basic_string<char>') and 'int')
        return base + rhs;
               ~~~~ ^ ~~~

Followed by a gazzilion

/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/bits/basic_string.h:6081:5: note: candidate template ignored: could not match 

I compile the code with following compile string clang++ -std=c++17 main.cpp

Upvotes: 0

Views: 54

Answers (1)

songyuanyao
songyuanyao

Reputation: 172994

The problem is that base + rhs; must be valid even std::is_same<T, std::string>::value is false; i.e. both statement-false and statement-true need to be valid no matter whether the condition is true or false.

You need the help of Constexpr If (since C++17). The statement-true or statement-false would be discarded according to the value of condition. E.g.

template<typename T> std::string test(std::string lhs, T rhs)
{

    std::string base = lhs + " = "; 
    if constexpr (std::is_same<T, std::string>::value)
    {
        return base + rhs;
    }
    else
    {
        return lhs + " = " + std::to_string(rhs);  
    }
}

Upvotes: 1

Related Questions