0

I am trying to solve a problem where I can define a class given an std::string only once, or else the compiler will throw an error.

Example:

Suppose we have a class Car which is initialized with its license plate. When creating it, the compiler is supposed to check if a Car instance with the exact same license plate string has already been created before.

My approaches so far:

I have been looking around for template-metaprogramming solutions which should create a simple registerable counter (example), however I fear that this doesn't really fit my needs.

Another idea was to create a simple define including the given license plate string, which but of course are unable to be created at compile-time since the license plate string is being passed only at run-time.

#include <string>
#include <vector>
#include <algorithm>
#include <iostream>

std::vector<std::string> myGlobalVector {};

class Car {
public:
  Car(std::string const& licensePlate);
  ~Car() = default;
  // ...

private:
    std::string _plate;
};

// ...

Car::Car(std::string const& licensePlate)
{
  // this would be the runtime version of what I want to achieve:
  const bool alreadyExists = std::any_of(
        myGlobalVector.begin(), 
        myGlobalVector.end(), 
        [&licensePlate](std::string const& otherPlate)
        {
            return otherPlate == licensePlate;
        });

    if (alreadyExists)
    {
        std::cerr << "License plate already registered. Exiting." << std::endl;
        exit(-1);
    }

    myGlobalVector.emplace(licensePlate);
}

int main() {
    Car someCar { "A4EM21F" };
    Car anotherCar { "F121EG4" };

    // ...

    // this should throw a compile-time error as 
    // given string has already been used before in this context
    Car lastCar { "A4EM21F" };
}

My only idea so far (which obviously won't compile but is supposed to illustrate what I want to achieve):

// ...
Car::Car(std::string const& licensePlate)
{
#ifndef CAR_##licensePlate
#define CAR_##licensePlate
    _plate = licensePlate;
#else
#error Car has already been created in your code!
#endif
}
// ...

Can anyone think of a way to check the occurrence of a string in a code snippet at compile-time?

I woult be grateful for helpful hints using any kinds of template-metaprogramming, type-trait or other topics.

16
  • Make a std::vector<std::string> static member for the class and whenever a new object is instanciated, you check if there a car with the same plate in the vector and if not, add it to the list. Would that work? Commented Oct 27, 2021 at 13:07
  • 1
    You certainly can’t do this across translation units; is it worthwhile otherwise? Commented Oct 27, 2021 at 13:09
  • With std::string_view instead of std::string, you might ensure at compile-time uniqueness of std::array<Car, N> MakeCar(). "Issue" is to pass C-string as argument simply. (gcc/clang has extension which allow to simply construct char sequence from C-strings literal). Commented Oct 27, 2021 at 13:13
  • I'd prefer static std::set<std::string>. Commented Oct 27, 2021 at 13:18
  • I think you can find use of a design pattern called singleton if I understood your question correctly. Commented Oct 27, 2021 at 13:34

1 Answer 1

1

In C++ 20 you can use the constexpr versions of the containers and with that implement your solution. But, then everything has to be constexpr. Not very meaningful.

I do not exactly know, what you want to achieve, but your design may be broken.

Sign up to request clarification or add additional context in comments.

1 Comment

It might indeed be, however the design unfortunately is not my main problem as I need to implement this solution for a big piece of software at my workplace. using constexpr was already in my mind, however for multiple reasons that's not possible for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.