Disthin guish char и wchar_t во время компиляции - PullRequest
1 голос
/ 09 мая 2020

У меня есть шаблон класса simplestring, который просто обрабатывает TChar * и его длину. TChar может быть как char, так и wchar_t. Вот простой метод левой обрезки:

simplestring<T> ltrim(const T* _s = nullptr) const
{
    const T* s = _s;
    if (s == nullptr)
    {
#if ( sizeof(T) == 1)
        s = " \t\r\n";
#else
        s = L" \t\r\n";
#endif
    }
    constexpr int len = tstrlen(s);
    find_first_not_of(s, len);
}

Я хочу, чтобы s было присвоено char *, когда T равно char, а в противном случае - wchar_t *. Он не компилируется. PS: Мой проект поддерживает C ++ 17.

Ответы [ 4 ]

2 голосов
/ 09 мая 2020

Еще один вариант:

template<typename CharT> foo(CharT const* &r);

template<> foo(char const *&r) { r = " \t\r\n"; }
template<> foo(wchar_t const *&r) { r = L" \t\r\n"; }
1 голос
/ 09 мая 2020

В C ++ 17 вы можете использовать if constexpr:

if constexpr (sizeof(T) == 1) // or (std::is_same_v<T, char>)
    s = " \t\r\n";
else
    s = L" \t\r\n";
1 голос
/ 09 мая 2020

Объединенные ответы Scheff и Evg, я сделал этот,

template<typename T>
struct simplestring
{
    static const T *default_trim;// = nullptr;

public:
    typedef std::basic_string<T> tstring;
    T* str = nullptr;
    unsigned int length = 0;

    void trim()
    {
        if constexpr(std::is_same<T, char>::value)
        {
            cout << "char";
            cout << default_trim;
        }
        else
        {
            cout << "wchar_t";
            wcout << default_trim;
        }
    }
};

template<>
const char* simplestring<char>::default_trim = "hello \t\r\n";
template<>
const wchar_t* simplestring<wchar_t>::default_trim = L"hello \t\r\n";

void test()
{
    simplestring<char> s;
    s.trim();
    simplestring<wchar_t> s2;
    s2.trim();
}

Спасибо им!

1 голос
/ 09 мая 2020

В C ++ 14 были введены шаблоны переменных .

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

Чтобы проиллюстрировать возможное решениеh, я сделал следующий MCVE:

#include <iostream>

template <typename T>
constexpr const T *init;

template <>
constexpr const char *init<char> = "string";

template <>
constexpr const wchar_t *init<wchar_t> = L"wstring";

template <typename T>
struct simplestring {
  const T *str;
  simplestring(const T *str = init<T>): str(str) { }
};

int main()
{
  simplestring<char> str;
  std::cout << "str: " << str.str << '\n';
  simplestring<wchar_t> wStr;
  std::wcout << "wStr: " << wStr.str << '\n';
}

Вывод:

str: string
wStr: wstring

Живая демонстрация на coliru


Шаблон переменной как static const член template class simplestring:

#include <iostream>

template <typename T>
struct simplestring {
  static const T *init;
  const T *str;
  simplestring(const T *str = init): str(str) { }
};

template <>
const char *simplestring<char>::init = "string";

template <>
const wchar_t *simplestring<wchar_t>::init = L"wstring";

int main()
{
  simplestring<char> str;
  std::cout << "str: " << str.str << '\n';
  simplestring<wchar_t> wStr;
  std::wcout << "wStr: " << wStr.str << '\n';
}

Вывод:

str: string
wStr: wstring

Демонстрация жизни на coliru

...