Подтвердить что ты не робот

С++ Идиоматические черты характера

У меня есть система признаков типа, которая находится в пространстве имен, например:

namespace my_namespace
{

template <typename T>
struct magic_traits
{
    static const int value = 0;
};

}

Поскольку люди ненавидят синтаксис специализированных шаблонов, у меня есть этот удобный маленький макрос:

#define DECLARE_MY_MAGIC_TRAITS(type_, value_) \
    namespace my_namespace                     \
    {                                          \
        template <>                            \
        struct magic_traits<type_ > {          \
            static const int value = value_;   \
        };                                     \
    }

}

Моя проблема в том, что это работает только для объявлений, сделанных в глобальном пространстве имен, поэтому черты для типа в другом пространстве имен выглядят следующим образом:

DECLARE_MAGIC_TRAITS(other_namespace::some_type, 9)

Хорошо, если люди знают обо всех правилах пространства имен, где находится DECLARE_MAGIC_TRAITS. Если они этого не делают и помещают декларацию в собственное пространство имен, они получат такие ошибки, как:

'magic_traits' is not a template!
Specialization of non-template 'other_namespace::my_namespace::magic_traits'

Это довольно запутанно для нового пользователя вашей библиотеки!

Есть ли способ сделать этот макрос способным определить специализацию magic_traits из любого места? Если это невозможно (как я подозреваю): Какие методы могут быть использованы для генерации более разумных сообщений об ошибках?

Я должен отметить, что мои пользователи в основном являются программистами на Python и имеют очень мало опыта на С++, поэтому все, что я могу сделать, чтобы сделать их жизнь проще, тем лучше.

4b9b3361

Ответ 1

Может быть, немного уродливо, но как насчет идеи:

namespace my_namespace
{

typedef bool The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace;

template <typename T>
struct magic_traits
{
    static const int value = 0;
};

}

#define DECLARE_MY_MAGIC_TRAITS(type_, value_) \
    namespace my_namespace {                   \
        typedef The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace CheckPrecondition; \
        template <>                            \
        struct magic_traits<type_ > {          \
            static const int value = value_;   \
        };                                     \
    }

Когда макрос используется неправильно, он генерирует ошибку, такую ​​как:

error: ‘The_DECLARE_MY_MAGIC_TRAITS_macro_should_be_used_in_the_global_namespace’ does not name a type
error: ‘magic_traits’ is not a template
error: explicit specialization of non-template ‘other_namespace::my_namespace::magic_traits’

Это может дать достаточно намека на то, что неправильно.

Ответ 2

Нет ничего лучше хорошей документации.

Вы должны сообщить пользователям своего макроса DECLARE_MAGIC_TRAITS, куда поместить макрос, и что писать внутри параметров (с примерами)

И сделайте сообщения об ошибках записью faq, чтобы пользователи нашли хороший ответ на то, что пошло не так.