Можно ли запретить автоматическое приведение типов при передаче объекта в качестве аргумента функции но оставить непосредственное приведение типов?

Есть такой код

#include<iostream>
#include<string>

using namespace std::string_literals;

using std::cout;
using std::endl;

struct MyClacc : public std::string
{
    int i;

    operator int() { return i; }

    int& operator=(int val) { return i = val; }
    std::string& operator=(std::string const & val) { return std::string::operator=(val); }
};

void foo(int) { cout << "foo(int)" << endl; }
void foo(double) { cout << "foo(double)" << endl; }
void foo(std::string const&) { cout << "foo(std::string&)" << endl; }

int main()
{
    MyClacc tmp;
    tmp = "qwerty"s;
    tmp = 42;

    int i = tmp;
    float f = tmp;
    std::string s = tmp;

    cout << i << endl;
    cout << f << endl;
    cout << s << endl;
    cout << tmp << endl; // хочу тут error

    foo(i);
    foo(f);
    foo(s);
    foo(tmp); // хочу тут error

    std::cin.get();
}

https://godbolt.org/z/nx7979aPd

Можно ли добится, чтобы работали все строки, кроме отмеченных? Т.е. я хочу чтобы каждый раз, когда какая-то функция может принять в качестве аргумента или int или string выдавалась ошибка компиляции. Но неявное приведение типов из int и string при этом работало. Такое возможно?
Сам класс MyClass, конечно же, можно править. Главное чтобы его видимое поведение в main было желаемым (всё работало кроме 2-х строк).


Ответы (1 шт):

Автор решения: Damir Hakimof
#include<iostream>
#include<string>

using namespace std::string_literals;

using std::cout;
using std::endl;

struct MyClacc : public std::string
{
  int i;

  operator int() { return i; }

  int& operator=(int val) { return i = val; }
  std::string& operator=(std::string const & val) { return std::string::operator=(val); }
};

void foo(int) { cout << "foo(int)" << endl; }
void foo(double) { cout << "foo(double)" << endl; }
void foo(std::string const&) { cout << "foo(std::string&)" << endl; }
// Эти функции помечены delete, они и не дают воспользоваться ими
void foo(const MyClacc& f) = delete;
std::ostream& operator<<(std::ostream&, const MyClacc&) = delete;
//------------------------------

int main()
{
  MyClacc tmp;
  tmp = "qwerty"s;
  tmp = 42;

  int i = tmp;
  float f = tmp;
  std::string s = tmp;

  cout << i << endl;
  cout << f << endl;
  cout << s << endl;
  cout << tmp << endl; // ERROR

  foo(i);
  foo(f);
  foo(s);
  foo(tmp); // ERROR

  std::cin.get();
}
→ Ссылка