Страницы

Поиск по вопросам

четверг, 7 марта 2019 г.

Непонятное поведение operator string ()

Есть некий класс, в очень упрощенном виде выглядит так:
class variant { public: variant (){};
template operator T () { return T(11); }
operator string () { string str = "sss"; return str; } };
и есть программа:
int main() { variant v1; int x1 = v1; // тут все хорошо (вызывается operator int ()) x1 = v1; // тут тоже все хорошо (вызывается так же operator int ())
variant v2; string s1 = v2; // тут все хорошо (вызывается operator string ()) s1 = v2; // тут получаю ошибку компиляции
return 0; }
немогу понять в чем дело, если задаю переменной типа string значение при инициализации то все нормально, но если пытаюсь присвоить переменной типа string значение получаю ошибку(с встроенными типами данных все хорошо):
error: ambiguous overload for 'operator=' (operand types are 'std::__cxx11::string {aka std::__cxx11::basic_string}' and 'variant')
что я делаю не так? как правильно перегрузить чтото вроде string operator= (variant)?
компилятор: gcc version 5.1.0 (MinGW-W64 project)


Ответ

Всё просто, в строке string s1 = v2; вызывается конструктор копирования std::string, у которого есть только один вариант аргумента: const std::string&. Поэтому происходит преобразование и всё работает.
С другой стороны, строка s1 = v2; вызывает std::string::operator= и тут уже вариантов аргументов куда больше, поэтому компилятор не может определить, в какой тип нужно конвертировать v2. Вылечить это можно только явным преобразованием.

На деле получается, что и с явным преобразованием получается та же ошибка. Дальше будут мои спекуляции почему так происходит, чтобы дать ответ точно — нужно штудировать стандарт.
Итак, строчка s1 = static_cast(v2); генерирует ту же самую ошибку, тогда как, как заметил Harry, такая строчка: s1 = static_cast(v2); работает как надо. Моё объяснение таково: в первом случае, конвертировать что-то в std::string можно из любого типа, одноаргументный конструктор которого имеет std::string, поэтому, эта строчка генерирует сразу пачку операторов преобразования и мы опять имеем неоднозначность.
С другой стороны, когда мы пытаемся преобразовать к ссылке на std::string, получается, что прямое преобразование побеждает — в непрямом нужно сначала создать std::string и только потом можно будет преобразовать к ссылке, т.е. 2 преобразования, а в первом случае нужно только одно.
Что нам всё это даёт? Даёт нам это понимание, что если написать код, который запретит шаблонному оператору преобразования участвовать в операциях, когда происходит конвертация в std::string, тогда наш код с преобразованием должен заработать:
template using EnableIfNotStr_t = std::enable_if_t::value>; class variant { public: variant() {};
template > operator T () { return T(11); }
operator std::string () const { std::string str = "sss"; return str; } }; //... s1 = static_cast(v2);

Установка пакетов на несколько машин одновременно

Есть сеть из n машин под управлением ОС Debian и доступ к ним по ssh. Также есть один диск с репозиторием.
Как параллельно установить набор пакетов с этого диска на все n машин?


Ответ

на какой-нибудь общедоступной машине «расшариваете» содержимое диска по любому подходящиему протоколу: http, nfs, samba, ftp и т.д. на каждой из n машин добавляете соответствующую строчку в /etc/apt/sources.list (а лучше — в отдельный файл в /etc/apt/sources.list.d/). на каждой из n машин обновляете список пакетов (sudo apt-get update). на кажлой из n машин устанавливаете нужные пакеты (sudo apt-get install ...).
как выполнить одну и ту же команду на множестве машин параллельно, я описывал, например, здесь: https://ru.stackoverflow.com/a/439394/178576

перетаскивание текста в редакторе Brackets

В таких текстовых редакторах, как Sublime Text и Notepad++ есть возможность перетаскивать текст. Например, Вы выделяете участок текста, нажимаете на клавишу Ctrl и мышкой перетаскиваете его в нужное место, при этом текст копируется. Если не нажимать клавишу Ctrl, то текст не копируется, а перемещается. В редакторе Brackets это не происходит.
Возможно ли в настройках редактора Brackets сделать какие либо изменения, что бы происходило перетаскивание? Если да, то напишите эту настройку.


Ответ

Отладка / Открыть файл настроек
"dragDropText": true

Конкатенация строк в PHP [закрыт]

Какая запись выглядит более эстетично, если цель - красивый код?
Такая
$user = $this->userName . implode("-", $this->birthDate);
Такая
$user = $this->userName; $user .= implode("-", $this->birthDate);
Или такая
$user = $this->userName; $birth = implode("-", $this->birthDate); $user .= $birth;
Пример написан от балды, так что строго не судите. По сути, мне интересно только одно - допустимо ли пихать в конкатенацию функции или понятнее когда "конкатенируются" только переменные. Сам склоняюсь к первому варианту.


Ответ

Субъективно мне нравится первый вариант, так как в нем одна строка и она укладывается в 80 символов (т.е. удовлетворяет стандарту PSR-2). Третий вариант неплох, вы выделяете $birth в отдельную переменную, однако, как мне кажется $this->birthDate в implode() и так дает достаточно информации, что речь идет о датах рождения. Отторжения или желания переделать ни один из вариантов не вызвал.

Аппроксимация движения пальца в кривые Безье

Существуют ли готовые решения для Android? Если нет, как лучше реализовать?


Ответ

Да, вы можете отследить точки начала и конца, max и min отклонения и использовать преобразования bezier. В классе Path, есть Квадратичные и Кубические преобразования кривых cubicTo и quadTo
Вот простой пример для теста с методом quadTo:
public class DrawBezierLine extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new DrawView(this)); }
class DrawView extends View { Paint p; public DrawView(Context context) { super(context); p = new Paint(Paint.ANTI_ALIAS_FLAG); p.setStrokeWidth(5); p.setStyle(Paint.Style.STROKE); }
@Override protected void onDraw(Canvas canvas) { p.setColor(Color.RED); canvas.drawPath(makeBezierLine(50, 50, 200, 300), p);
} } private Path makeBezierLine(float x1, float y1, float x3, float y3) { final Path path = new Path(); path.moveTo(x1, y1); final float x2 = 0; final float y2 = 200; path.quadTo(x2,y2, x3,y3); return path; } }
где x1,y1 -начальная точка. x3,y3 - конечная точка, x2,y2 - точка отклонения.
Но для вашего примера, больше подойдет кубическое преобразование, очень часто используется в рисовалках.
Добавлю: Интерполяторы используют аналогию сложных кривых Безье и могут быть использованы, для решения многих задач. Также никто вам не мешает создать свой алгоритм преобразования, используя свои данные, что может быть актуальней и возможно проще.

среда, 6 марта 2019 г.

Сколько времени ajax запрос ждет ответа от сервера?

Сколько времени .ajax метод ждет ответ? В моем примере он обращается к сервлету, и если в сервлете перед отправкой ответа добавить хотя бы секунду Thread.sleep(), то вызывается обработчик ошибки error, если его убрать, то ответ обрабатывается корректно. Просто в более сложном примере, когда сервлет уже в свою очередь к серверу обращается, что тоже занимает время, ответ опять-таки не приходит. Если вообще понятие времени ожидания запросом ответа?
Вот код ajax запроса
$(document).ready(function () { $("#login-button").click(function () { var userPassword = $("input#userPassword").val(); var userLogin = $("input#userLogin").val(); $.ajax({ type: "POST", url: "login", dataType: "text", data: {login: userLogin, password: userPassword}, success: function (data) { alert("Successful request! Data is " + data.toString()); }, error: function (jqXHR) { console.log(jqXHR); } }); }); });
Метод service в сервлете
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Даже если на секунду включить, ответ не проходит /*try { Thread.sleep(1000); } catch(InterruptedException ex) { Thread.currentThread().interrupt(); }*/
response.setContentType("text/plain"); response.setCharacterEncoding("UTF-8"); response.getWriter().print("test");
}


Ответ

Для начала стоит убедиться, что возврат ajax-запроса происходит из-за нехватки времени - для этого проверяем статус ответа:
error: function(jqXHR, status, e) { if (status === "timeout") { alert("Время ожидания ответа истекло!"); } else { alert(status); // Другая ошибка } }
Если все же ошибка связана с timeout, то можно вручную установить нужное значение, явно указав значение ожидания в миллисекундах:
Set a timeout (in milliseconds) for the request. This will override any global timeout set with $.ajaxSetup(). The timeout period starts at the point the $.ajax call is made; if several other requests are in progress and the browser has no connections available, it is possible for a request to time out before it can be sent.
Стандартное значение timeout зависит от конкретной реализации браузера, судя по ответу на enSO.

Вынести load в отдельный метод

$this->load->view('header'); $this->load->view('workmenu'); $this->load->view('all_gk'); $this->load->view('footer');
Вот в этом коде мне не нравится что во всех контролерах мне надо вызывать загрузку хедера, меню, и футера, их можно как то вынести?


Ответ

Из-за отсутствия layout в Codeigniter, нужно прибегать к костылям. Вот решение данной проблемы: Создается библиотека application/libraries/my_layout.php
class MY_Layout extends CI_Controller {
// пути к файлам вида public $header = 'header'; public $footer = 'footer';
// метод получает на вход два параметра: название вида и данные для него public function content($views = '', $data = '') { // загружаем header if ($this->header) { $this->load->view($this->header, $data); }
// загружаем основной контент, который может иметь больше одного вида if (is_array($views)) { foreach ($views as $view) { $this->load->view($view, $data); } } else { $this->load->view($views, $data); }
// загружаем footer if ($this->footer) { $this->load->view($this->footer); } } }
В используемом контроллере достаточно подключить нашу библиотеку и обратиться к нужному виду через $this->my_layout->content('user/test', $data);
class User extends CI_Controller {
public function __construct() { parent::__construct(); $this->load->library('MY_Layout'); }
public function test() { $data['title'] = 'dynamic_string'; $this->my_layout->content('user/test', $data); } }
Вы так-же можете передавать несколько видов одновременно:
$data['title'] = 'dynamic_string'; $views = array( 'menu' => 'menu', 'content' => 'user/test' );
$this->my_layout->content($views, $data);
И в завершении, вы можете отключать часть вашего layout'a или использовать вместо него другой вид.
$this->my_layout->header = 'user/custom_user_header'; // or turn off header $this->my_layout->header = FALSE;
Пример был взят: Источник . Удачного кодинга...