2016-08-22 2 views
1

Я наткнулся на небольшую проблему с небольшим кодом, который я делаю, изучая C++ 11/14. В основном у меня есть класс отладки, который я хочу обрабатывать при печати сообщений. Большинство классов отладки/регистрации имеют уровни сортировки журналов, но я хочу использовать флаг для каждый сообщение, которое у меня есть.Двойная частичная специализация шаблона для класса

Для этого у меня есть немного перечисления, где я определяю свои флаги и их значения:

enum DebugFlag { 
    Flag1 = 0, 
    Flag2 = 1, 
    Flag3 = 2 
}; 

Aditionally, у меня есть класс отладки, который я сумел специализироваться для типов флага, и она работает очень хорошо ,

template<DebugFlag T> 
class Debug { 
public: 
    template <typename U> 
    static void print(U &&arg) {} 
}; 

template <> 
class Debug<static_cast<DebugFlag>(1)> { 
public: 
    static void print(std::string &&message) { 
     std::cerr<<message<<"\n"; 
    } 

    static void print(std::ostream &message) { 
     std::cerr<<DebugStream()().str()<<"\n"; 
     DebugStream()().str(""); 
     DebugStream()().clear(); 
    } 

    static void print(std::string &message) { 
     std::cerr<<message<<"\n"; 
    } 
}; 

Для вызова этого класса, я использую вызов, как:

Debug<Flag1>::print("Message\n"); // should not do anything with Flag1 compiled to 0 value 
Debug<Flag2>::print("Message\n"); // should work 

Теперь я хотел расширить этот класс также принимать bool значения, поэтому вызовы, как это будет работать:

Debug< Flag2<2 >::print("Message\n"); // should not do anything with Flag1 compiled to 2 value 
Debug< Flag2<1 >::print("Message\n"); // should work 

Проблема: мне нужна вторая частичная специализация для моего класса Debug, то есть bool, и я не могу точно определить, что для этого синтаксис. Это самое близкое, что я придумал, но до сих пор не могу понять, что я делаю неправильно, или если это возможно, не делая второго класса и меняя способ, которым я хочу, чтобы мой звонок выглядел так: http://cpp.sh/6yemn

ответ

2

Я точно не понимаю, как вы хотите использовать свой класс, но вот что-то работает.

template <typename T, T v = T()> 
class Debug {}; 

template <> 
class Debug<Flag, Flag2> { 
public: 
    void f() { std::cout<<"This is good\n"; } 
}; 

template <> 
class Debug<bool, true> { 
public: 
    void f() { std::cout<<"This is good too\n"; } 
}; 

Проблема заключается в том, что вам необходимо указать тип: хотите ли вы использовать bool или Flag, а затем значение. Вы можете создать экземпляр этого класса, как так:

Debug<bool, true> trueDebug; 
Debug<Flag, Flag2> flag2Debug; 

Другие случаи не будут иметь функцию f, если вы не добавите специализации. Например:

template <Flag v> 
class Debug<Flag, v> { 
public: 
    void f() { std::cout<<"This is bad\n"; } 
}; 

Live example

+0

Здравствуйте, спасибо за ответ. Возможно, я мог бы смутить этот пример с помощью примера 'Debug ', 'int' и' Flag'. В действительности все мои вызовы будут либо 'Debug ', 'Debug ,' или 'Debug '. То, что я собрал из вашего ответа, состоит в том, что у меня нет возможности иметь 2 частичных реализаций из двух разных типов (т.е. true и все флаги boolean, равные 1), используя 1 параметр шаблона (как в коде I, представленном в вопрос, а не ссылка, которая работает). –

+0

C++ 17 позволит избавиться от первого параметра, поэтому ожидаемый синтаксис. (с 'template class Debug;') – Jarod42

+0

Для моего любопытства, разумеется, что мне нужно знать, что искать или предоставлять ссылку для проекта C++ 17? Я действительно искал эту проблему в течение нескольких часов, потому что она казалась разрешимой. Печальная часть заключается в том, что я мог бы сделать это очень легко, используя '# define', но я пытаюсь избежать их вообще сейчас в C++ для const/constexpr и шаблонов, но не всегда так легко получить его правильно , –