How to differ multiple typedefs of std::string

Viewed 48

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()?

1 Answers

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"});
}
Related