2
\$\begingroup\$

I am implementing a library in C/C++11 and I have chosen to follow Google C++ Style Guide as I also use this style guide in my code.

As such all classes and types (including typedefs and using) start with a capital letter.

However I have reached a conflict when implementing some traits.

For instance I have a RemoveOptional trait:

template <class T>
struct RemoveOptional {
  using Type = T;
};

template <class T>
struct RemoveOptional<utils::Optional<T>> {
  using Type = T;
};

that I can use like this:

utils::RemoveOptional<utils::Optinal<int>>::Type

But for the traits like IsXXX I have chosen to inherit std::true_type or std::false_type in order to be used like the std traits:

template <class T>
struct IsOptional : std::false_type {
};

template <class T>
struct IsOptional<Optional<T>> : std::true_type {
};

so this trait is used like this:

utils::IsOptional<utils::Optional<int>>::value
utils::IsOptional<utils::Optional<int>>::value_type

And value_type conflicts with my naming conventions as it should be ValueType.

As far as I see I have 3 options:

  • Modify all of my traits to follow the std convention.

    • Advantages: my traits can be checked against the std::true_type and std::false_type.
    • Disadvantages: my library is inconsistent.
  • Discard the std::true_type and std::false_type and make all my traits following my convention.

    • Advantages: my library is consistent.
    • Disadvantages: my traits can't be checked against std::true_type and std::false_type.
  • Leave as it is now.

    • Advantages: my traits can be checked against std::true_type and std::false_type.
    • Disadvantages: my library is inconsistent (even my traits are inconsistent between each other).

What should I do?

\$\endgroup\$
  • \$\begingroup\$ I am not certain this question belongs on CodeReview. Perhaps Programmers is a better site? \$\endgroup\$ – rolfl Jan 4 '14 at 16:50
  • \$\begingroup\$ When that guide isn't discussing small stuff like naming conventions and indentation, it promotes some of the worst coding practices imaginable. Don't use it for your code if you want to be taken seriously (or at least make a disclaimer like "naming convention follows GSG C++"). \$\endgroup\$ – Cubbi Jan 5 '14 at 15:58
  • \$\begingroup\$ Don't use the "Googel Style Guide". It is good for internal google usage only. Its guidance is outdated and bad in many places for use with real C++. \$\endgroup\$ – Martin York Jan 6 '14 at 21:34
  • \$\begingroup\$ Though I do agree with using a capitol letter as the first letter of a type name. It helps distinguish types from other identifiers. But follow the standard conventions when mirroring standard types. \$\endgroup\$ – Martin York Jan 6 '14 at 21:35
  • \$\begingroup\$ @LokiAstari What guides do you recommend for C++? I know it's a subjective question, and that's why I don't post a formal question on SO, but I am really interested in a good (and fairly used) C++ style guide. \$\endgroup\$ – bolov Jan 6 '14 at 23:22
2
\$\begingroup\$

There is no single correct answer in all circumstances. You have to weigh the costs and benefits of the alternatives. Oddly enough my analysis seems to match yours, but here's one additional alternative you didn't explicitly cover:

  • Add redundant typedefs. All types you create will follow your standard, and those from the standard library will not. However you can easily provide aliases that expose parts of the standard library using names of your choosing. This is a little more code than the first option, and provides an opportunity for users of your class to use either name they like. If more than one name is used, the readability of the code can suffer. As such, while this initially may look like it combines the best of both extremes, in reality it also offers the worst.

    template <class T>
    struct IsOptional : std::false_type {
        using Type = std::false_type::value_type;
        using Value = std::false_type::value;
    };
    
    template <class T>
    struct IsOptional<Optional<T>> : std::true_type {
        using Type = std::true_type::value_type;
        using Value = std::true_type::value;
    };
    

However, once you're done writing the library, I would posit this is not all that important. I do not routinely use std::true_type or std::false_type when consuming a library. Template specialization is typically used to achieve two objectives at the same time:

  • Make the classes easy to use in flexible ways
  • Make the code that uses the classes really fast

Neither of these objectives really involve the consumers of the library having to care about the names of the types used in specializing its templates.

And thus my answer is this: don't sweat it. Do what makes you, and anyone else who is helping to implement your library, happy. This probably means choose the least amount of work, leaving you with mismatched conventions, but the ability to leverage knowledge of working with the standard library, but could mean writing your own TrueType and FalseType classes that follow your chosen naming conventions.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thank you. I work alone on it so I am the only one who needs to be happy :). I know I tend to overthink this kind of things so I will leave it now as it is. I think I will write my own TrueType and FalseType later on. \$\endgroup\$ – bolov Jan 4 '14 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.