0
#include <cstdio>
#include <string>
constexpr char str[] = "/home/qspace/etc/client/mmkvcfgsvr_test_byset_cli.conf";

void test(bool a)
{
    printf("b=%d",a);
}

void test(const std::string& s){
    printf("s=%s",s.c_str());
}
int main()
{
  test(str);
  return 0;
}

Like this code, the C++ compiler will convert char* to bool and then call the first function, which is inconsistent with my original intention. Is there any way to prevent the compiler from performing type conversions that I don't want? Like "-fno-permissive", but unfortunately, it doesn't work.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
komonzhang
  • 67
  • 5
  • 2
    Did you try explicitly constructing a `std::string{str}`? – Sam Varshavchik Jan 06 '21 at 12:23
  • C doesn't have function overloading – Kanony Jan 06 '21 at 12:24
  • You just need to set the correct argument type, instead of `std::string &`, use `char *` – fedemengo Jan 06 '21 at 12:24
  • Do not tag C for C++ questions. – Eric Postpischil Jan 06 '21 at 12:27
  • 1
    @fedemengo: Defining a `test` as `void test(char * s)` does not result it in being called over the `void test(bool a)`, as tested in Apple Clang 11.0.0. Making it `void test(const char *s)` does. – Eric Postpischil Jan 06 '21 at 12:31
  • To clarify your question, there are ways to define a `test` that will be called in preference to `void test(bool a)`, such as `void test(const char *s)`, and there are ways to change the argument so that `void test(const std::string &s)` is called rather than `void test(bool a)`, but are you specifically asking not for those but for a way to suppress the conversion to bool given the two function definitions as shown? – Eric Postpischil Jan 06 '21 at 12:33
  • @EricPostpischil right, replacing `std:: string &` with `char *` will result in `const char * s` which is what I meant – fedemengo Jan 07 '21 at 13:05

2 Answers2

0

You're mixing C and STL types (char array vs std::string). There are two solutions. The immediately obvious solution is to create a temporary std::string object every time you wish to pass a char array into a function expecting std::string.

test(std::string(str));

The other solution, which I prefer, is to avoid C types altogether. To create a string constant, use STL type directly:

const std::string str {"/home/qspace/etc/client/mmkvcfgsvr_test_byset_cli.conf"};

If you wish to retain constexpr see this thread: Is it possible to use std::string in a constexpr?

Tarmo
  • 3,728
  • 1
  • 8
  • 25
0

How to explicitly call the specified overload function?

  • Convert the argument at call site: test(std::string(str));
  • Take expected address of overload function: static_cast<void(*)(const std::string&)>(print)(str);

Is there any way to prevent the compiler from performing type conversions that I don't want?

You might add a catch-all overload as deleted: template <typename T> void test(const T&) = delete;

Alternatively, in C++17, you might do the "dispatching" manually:

template <typename T>
void test(const T& t)
{
    static_assert(std::is_constructible_v<std::string, T>
               || std::is_convertible_v<T, bool>);

    if constexpr (std::is_constructible_v<std::string, T>) {
        const std::string& s = t;
        printf("s=%s", s.c_str());
    } else if constexpr (std::is_convertible_v<T, bool>) {
        printf("b=%d", bool(t));
    }
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302