Объявите имя модуля классов для регистрации - PullRequest
0 голосов
/ 25 марта 2010

В настоящее время я добавляю некоторые функции в нашу библиотеку журналов. Одним из них является возможность объявить имя модуля для класса, который автоматически добавляется к любым сообщениям журнала, записываемым из этого класса. Однако, если имя модуля не указано, ничего не добавляется. В настоящее время я использую класс trait, который имеет статическую функцию, которая возвращает имя.

template< class T >
struct ModuleNameTrait {
    static std::string Value() { return ""; }
};

template< >
struct ModuleNameTrait< Foo > {
    static std::string Value() { return "Foo"; }
};

Этот класс можно определить с помощью вспомогательного макроса. Недостатком является то, что имя модуля должно быть объявлено вне класса. Я хотел бы, чтобы это было возможно в классе. Кроме того, я хочу иметь возможность удалить весь лог-код, используя директиву препроцессора. Я знаю, что с помощью SFINAE можно проверить, есть ли у аргумента шаблона определенный член, но поскольку другие люди, которые не так дружат с шаблонами, как я, должны будут поддерживать код, я ищу гораздо более простое решение. Если их нет, я буду придерживаться подхода черт.

Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 25 марта 2010

Я бы хотел, чтобы это было возможно в классе.

Это невозможно при вашем подходе, должны быть объявлены явные специализации в пространстве имен, членом которого является шаблон.

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

template<class T> const char* const name(const T&) { return ""; }

class X;
const char* const name(const X&) { return "X"; }

struct X {
    // prints "X"
    void f() { std::cout << name(*this) <<  std::endl; }
};

struct Y {
    static const char* const name(const Y&) { return "Y"; }    
    // prints "Y"
    void f() { std::cout << name(*this) << std::endl; }
};

struct Z {
    // prints ""
    void f() { std::cout << name(*this) << std::endl; }
};

Если вы хотите определить name() только в классах, а не снаружи, конечно, нет необходимости в шаблонах или перегрузках:

const char* const name() { return ""; }

struct X {
    static const char* const name() { return "X"; }    
    // prints "X"
    void f() { std::cout << name() << std::endl; }
};

struct Y {
    // prints ""
    void f() { std::cout << name() <<  std::endl; }
};
0 голосов
/ 25 марта 2010

Я не уверен, насколько простым должно быть решение, вот очень простое, которое я использовал несколько раз.

Существует базовый класс ClassName с чем-то вроде:

class ClassName
{
    string name;
public:
    ClassName( string strName = "" ) : name(strName)
    {
         if( strName.length() )
               strName += ": ";
    }
    string getName()
    {
        return name;
    }
};
#ifdef _DEBUG
    #define LOG cout << getName() 
#else
    #define LOG cout
#endif

И другой класс унаследует его, дав ему имя:

class Session : virtual public ClassName
{
public:
    Session() : ClassName("Session")
    {
    }

    void func()
    {
         LOG << "Some log here" << endl;
    }
};
...