1

I have these typedefs for std::string and a function

using FirstName = std::string;
using SecondName = std::string;

void DoSmth(const FirstName& f, const SecondName& s) 
{
    /* some mixture of f.empty(), s.size(), f.substr() and other useful std::string member functions*/
}

How can I teach the compiler to warn me in the next DoSmth call:

void CallDoSmth()
{
   FirstName f = "Sher";
   SecondName s = "Andrei";
   DoSmth(s, f);
}

Here is one implementation with tags. Another solution would be:

struct FirstName {
    std::string value;
    explicit FirstName(std::string str) : value(std::move(str)) {}
};

In both presented solutions there is an overhead to call member functions of a std::string. Is there a way to get an error in CallDoSmth(), but do not change anything in DoSmth()?

SherAndrei
  • 528
  • 3
  • 14

1 Answers1

1

You are not very far from the truth: https://godbolt.org/z/YaTbYhjo9

#include <string>
#include <iostream>

using first_name = std::string;
using second_name = std::string;

// no type safety
void add_record(const std::string& f, const std::string& s)
{
    std::cout << "My name is " << s << " " << f << ", but everybody calls me... "
     << f << std::endl;
}

struct first_name_tag
{
    const std::string& value;
};

struct second_name_tag
{
    const std::string& value;
};

// type safe version
void add_record(first_name_tag f, second_name_tag s)
{
    return add_record(f.value, s.value);
}

int main()
{
    add_record(first_name_tag{"Giorgio"}, second_name_tag{"Giovanni"});
}
Sergey Kolesnik
  • 3,009
  • 1
  • 8
  • 28
  • Is there a way to save names of input argument types for `add_record` (in my example it is `DoSmth`)? What I need is to reach typesafety by changing typedefs `FirstName` and `SecondName` into some classes, but i do not know is it possible. I have a feeling that there will be problems with implicit casting to `std::string` in some cases. – SherAndrei Dec 06 '21 at 15:22
  • @SherAndrei what do you mean by "save names of input argument types"? You can add to your wrapper-classes `explicit operator const std::string&() const` and an implicit conversion to `std::string` will not be possible – Sergey Kolesnik Dec 06 '21 at 15:29