mimetype C++

Изображение пользователя nitrofox.

У меня есть огромная библиотека музыки. И в куче файлов есть в описание силки. Я написал программку которая находит силки в описание и удаляет их. Сделал.. Но хочется добавить еще маленькую функцию. Как можно получить mime файла.
Допустим Music/Alizee - Moi... Lolita.mp3 как получить его mimetype "audio/mpeg". Сейчас я по расширению файла могу выборку файлов делать. Хочу добавить возможность и по mime делать выборку.

0
fox4 - 12 Август, 2018 - 12:56
Изображение пользователя fox4.

Как можно получить mime файла.
Допустим Music/Alizee - Moi... Lolita.mp3 как получить его mimetype "audio/mpeg"

Detector mime

Пример использования Detector

0
nitrofox - 13 Август, 2018 - 11:35
Изображение пользователя nitrofox.

Спасибо.
Приятно что в с++ появилось filesystem =). Я вообще удивлен что удалось очень простую задачу на С++ решить очень просто и быстро. С пол часа понадобилось чтобы сделать все что нужно. И 4 часа чтобы переделать с кучей шаблонов и constexpr=)
Появилась бы еще возможность с unicode работать без лишних телодвижений...

У меня еще один вопрос.
if constexpr (std::is_same_v<FilterCallback, DefaultArgument_t>) {
   ...
} else if constexpr (std::is_invocable_r_v<bool, FilterCallback, fs::path>) {
   ...
} else {
   ???
}

Можно ли остановить компиляцию и выдать ошибку если компилятор доберется до последнего else.

0
Гость - 13 Август, 2018 - 21:00

Можно ли остановить компиляцию и выдать ошибку если компилятор доберется до последнего else

Не очень понятна суть вашей идеи...

Ошибки синтаксиса и Ошибки выполнения это как бы разные сущности.
Вы кого пытаетесь поймать в данном случае.
Мне кажется что Вы ловите exeption системной библиотеки и непонятно как правильно ее обработать.
Или я ошибаюсь ?

0
fox4 - 13 Август, 2018 - 21:05
Изображение пользователя fox4.

Можно ли остановить компиляцию и выдать ошибку если компилятор доберется до последнего else.
Не очень понятна суть вашей идеи...
Ошибки компиляции и ошибки выполнения это как бы две разные сущъности...
Вы что пытаетесь поймать в данном случае...
Если это Exeption системы то он и обрабатывается по своим правилам.

0
nitrofox - 14 Август, 2018 - 00:20
Изображение пользователя nitrofox.

Ну во всех статях о С++17 приводят подобный пример использования if constexpr
В C++14 писали 2 шаблоных функции и при помощи enable_if уже уточнять когда будет вызвана функция.
// Для string
template <class T>
std::enable_if_t<std::is_same_v<std::string, T>> print(T t) {
  std::cout << "String(Size: " << t.size() << ") = \"" << t << "\""
            << std::endl;
}
// Для чисел
template <class T>
std::enable_if_t<std::is_integral_v<T> || std::is_floating_point_v<T>> print(
    T t) {
  std::cout << "Num = " << t << std::endl;
}

С приходом C++17 появился if constexpr. Он во время компиляции отбрасывает не подходящие ветки условия. И теперь можно написать
template <class T>
void print(T t) {
  if constexpr (std::is_same_v<std::string, T>) {
    std::cout << "String(Size: " << t.size() << ") = \"" << t << "\""
              << std::endl;
  } else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) {
    std::cout << "Num = " << t << std::endl;
  } else {
  }
}

Если я вызову функцию print(10), то первая ветка if будет отброшена на этапе компиляции и компилятор не будет пытаться у int искать метод size. Оба варианта будут одинаково работать если им передать string или число. Но если попытаюсь передать любой другой тип, то вариант с enable_if не будет компилироваться. А варианте с if constexpr скомпилируется и просто нечего не будет делать. А это не очень хорошо. Такое поведении мне не очень подходит. Короче я уже сам с трудом могу понять что я хочу =)

У меня в проекте есть
**
if constexpr (std::is_invocable_r_v<bool, decltype(cal), fs::path&>) {
     if (cal(item) == false) break;
} else if constexpr (std::is_invocable_r_v<void, Callback,
                                                     fs::path&>) {
     cal(item);
}

**

если я ошибусь и вместо колбекфункции передам розового слона... То моя функция без ошибок будет вызвана и просто нечего не сделает. Вот у меня возник вопрос. Можно ли как-то вывести ошибку и прекратить компиляцию если мы попали в else.

+1
MacLeod - 15 Август, 2018 - 22:12
Изображение пользователя MacLeod.

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

template <class T>
void print(T t) {
  constexpr auto isInt = std::is_same<T,int>::value;
  constexpr auto isFloat = std::is_floating_point<T>::value;
  constexpr auto isString = std::is_same<std::string, T>::value;

  static_assert(isString || isInt || isFloat); // <- тут грохнется на компиляции

  if constexpr (isString) {
    std::cout << "String(Size: " << t.size() << ") = \"" << t << "\""
              << std::endl;
  } else if constexpr (isInt || isFloat) {
    std::cout << "Num = " << t << std::endl;
  } else {
  }
}

0
fox4 - 15 Август, 2018 - 22:36
Изображение пользователя fox4.

Здесь советом помочь не могу мои знания остановились приблизительно на C++ 11. Вы определитесь а так ли нужно Вам решать эту задачу через шаблоны. Многие программисты через чур этим увлекаются. В итоге получается как на картинке

0
yadevel - 30 Август, 2018 - 01:24

просмотрел тред.
рекомендую не заморачиваться с шаблоном, а просто написать несколько отдельных функций с перегрузкой. сам решал подобную проблему несколько раз.
можно написать функции print(int) и print(string) и пользовать вызовы print(10) и print("blabla"), проще и нагляднее.
есть вариации для удобства, потом по интересу.

0
nitrofox - 30 Август, 2018 - 03:27
Изображение пользователя nitrofox.

Просто у меня функция может принимать 2 варианта Callback функций. void(fs::path&) или bool(fs::path&). Мне кажется если использовать перегрузку... Будет очень много дублированного кода. А разница будет всего в одной строке. И если мне нужно будет что-то поправить, придется это делать в 2 вариантах функций. Шаблонная магия и if constexpr помогает чуток сэкономить. Заставить эти перегрузки генерировать сам компилятор.

0
yadevel - 31 Август, 2018 - 22:37

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

но если сильно хочется через if constexpr, то ставь static_assert(false, "blabla") в ветку else

0
MacLeod - 5 Сентябрь, 2018 - 00:23
Изображение пользователя MacLeod.

если сильно хочется через if constexpr, то ставь static_assert(false, "blabla") в ветку else
Не будет работать. Точнее, это будет прерывать компиляцию всегда.

0
yadevel - 6 Сентябрь, 2018 - 00:45

может gcc как то особо работает, но на VS2017 без проблем
#include "stdafx.h"
#include <string>
#include <iostream>

template<typename T>
void print(T const& val)
{
  if constexpr(std::is_same_v<std::string, T>)
  {
    std::cout << "String(Size: " << val.size() << ") = \"" << val << "\"" << std::endl;
  }
  else if constexpr(std::is_arithmetic_v<T>)
  {
    std::cout << "Num = " << val << std::endl;
  }
  else
  {
    static_assert(false, "unexpected");
  }
}

int main()
{
  print(10);
  print(std::string("blabla"));
  //print("blabla");
  return 0;
}

если раскомментить строку, компиляция прервётся.

0
nitrofox - 6 Сентябрь, 2018 - 01:15
Изображение пользователя nitrofox.

gcc и clang не компилирует
int main() {
  if constexpr (true) {
  } else {
    static_assert(false);
  }
}

0
yadevel - 6 Сентябрь, 2018 - 01:50

VS тоже не компилирует.
но если перенести в шаблон, всё норм.
надо будет поизучать стандарт на эту тему.

0
nitrofox - 24 Сентябрь, 2018 - 14:45
Изображение пользователя nitrofox.

Если верить сайту http://scrutator.me/post/2017/10/07/cpp17_lang_features_p2.aspx
clang и gcc поступает правильно. По стандарту выражение static_assert(false) является некорректным. А в if constexpr код должен быть корректным.
Если верить сайту https://en.cppreference.com/w/cpp/language/if ....
Можно с помощью костыля заставить работать static_assert в шаблонной функции.

#include <iostream>
#include <string>
template <class T>
struct dependent_false : std ::false_type {};
template <typename T>
void print(T const& val) {
  if constexpr (std::is_same_v<std::string, T>) {
    std::cout << "String(Size: " << val.size() << ") = \"" << val << "\""
              << std::endl;
  } else if constexpr (std::is_arithmetic_v<T>) {
    std::cout << "Num = " << val << std::endl;
  } else {
    static_assert(dependent_false<T>::value);
  }
}
int main() {
  print(10);
  print(std::string("blabla"));
}

Теперь код будет нормально компилироваться.
https://wandbox.org/permlink/2uHNXRx73cSVi3vg

0
MacLeod - 27 Сентябрь, 2018 - 02:57
Изображение пользователя MacLeod.

Рукалицооо...
Если вам так "горит" что-то засунуть в else, то засуньте static_assert из моего примера выше. С constexpr аргументом он будет полностью корректным.
Просто у меня как-то привычка сложилась: прерывающие проверки делать в начале функции, а не в заднице =)

0
nitrofox - 27 Сентябрь, 2018 - 12:28
Изображение пользователя nitrofox.

Я не программист =). И воспользовался языком С++ чтобы автоматизировать поиск и удаления ссылок из коллекции музыки. Уверен что на bash это можно было сделать проще. Но... Я не очень люблю bash.
К сожалению я удалил уже проект. По памяти: Я хотел реализовать класс fsWalker. И у меня вышло очень не красиво.

std::enable_if_t<
(std::is_invocable_r_v<void, CallBack,fs::path&> || std::is_invocable_r_v<bool, CallBack,fs::path&>) &&
(std::is_same_v<Filter, DefaultArgument_t> || std::is_invocable_r_v<bool, Filter, fs::path>)
>
fsWalker(fs::path path, CallBack cal, Filter f) {}

int main() {
  fsWalker("/home/DooM/Music/", [](fs::path& p){std::cout << p << std::endl;},defaultArgument);
  fsWalker("/home/DooM/Music/", [](fs::path& p){std::cout << p << std::endl;}, FilterExtension("mp3", "m4a"));
}

Я хотел избавится от enable_if. Тема уже не актуальна =)

Отправить комментарий

CAPTCHA на основе изображений
Введите цифры