Почему мои приложения автозапуска действуют странные на Vista?

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

#include 
#include 
#include 

/*  Here we apply the accepted answer's technique to probe for the
    the existence of `E T::operator*() const`
*/
template
struct has_const_reference_op
{
    template struct SFINAE {};
    template static char Test(SFINAE*);
    template static int Test(...);
    static const bool value = sizeof(Test(0)) == sizeof(char);
};

using namespace std;

/* Here we test the `std::` smart pointer templates, including the
    deprecated `auto_ptr`, to determine in each case whether
    T = (the template instantiated for `int`) provides 
    `int & T::operator*() const` - which all of them in fact do.
*/ 
int main(void)
{
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op,int &>::value << endl;
    return 0;
}

Построено с GCC 4.6.3 , программные выходы 110 - информируя нас о том, что T = std::shared_ptr предоставляет not , предоставить int & T::operator*() const.

Если вы еще не разумны в этом вопросе, то посмотрите на определение std::shared_ptr в заголовке пролить свет. В этой реализации std::shared_ptr происходит из базового класса, из которого он наследует operator*() const. Таким образом, экземпляр шаблона SFINAE, который представляет собой «поиск» оператора для U = std::shared_ptr, не будет выполняться, поскольку std::shared_ptr не имеет operator*() в своем собственном праве, а создание экземпляра шаблона не «наследует».

Эта защелка не влияет на хорошо известный подход SFINAE, используя «Theofofofof () Trick», для обнаружения только того, имеет ли T некоторая функция-член mf (см., например, этот ответ и Комментарии). Но установление того, что T::mf существует, часто (обычно?) Не достаточно хорошо: вам также может потребоваться установить, что у него есть желаемая подпись. Вот где проиллюстрирована техническая оценка. Указанный вариант желаемой сигнатуры вписывается в параметр типа шаблона, который должен удовлетворять &T::mf для успешного использования зонда SFINAE. Но этот метод экземпляра шаблона дает неправильный ответ, когда T::mf унаследован.

Безопасный метод SFINAE для интроспекции компиляции T::mf должен избегать использования &T::mf в аргументе шаблона для создания экземпляра типа от которого зависит разрешение шаблона функции SFINAE. Вместо этого разрешение функции шаблона SFINAE может зависеть только от точно соответствующих деклараций типа, используемых в качестве типов аргументов перегруженной функции зондирования SFINAE.

. В ответ на вопрос, который соблюдает это ограничение, я проиллюстрирую обнаружение компиляции E T::operator*() const для произвольных T и E. Тот же шаблон применит mutatis mutandis для проверки любой другой сигнатуры метода участника.

#include 

/*! The template `has_const_reference_op` exports a
    boolean constant `value that is true iff `T` provides
    `E T::operator*() const`
*/ 
template< typename T, typename E>
struct has_const_reference_op
{
    /* SFINAE operator-has-correct-sig :) */
    template
    static std::true_type test(E (A::*)() const) {
        return std::true_type();
    }

    /* SFINAE operator-exists :) */
    template  
    static decltype(test(&A::operator*)) 
    test(decltype(&A::operator*),void *) {
        /* Operator exists. What about sig? */
        typedef decltype(test(&A::operator*)) return_type; 
        return return_type();
    }

    /* SFINAE game over :( */
    template
    static std::false_type test(...) {
        return std::false_type(); 
    }

    /* This will be either `std::true_type` or `std::false_type` */
    typedef decltype(test(0,0)) type;

    static const bool value = type::value; /* Which is it? */
};

В этом решении перегруженная функция зонда SFINAE test() «вызывается рекурсивно», , (Конечно, он вообще не вызывается вообще, он просто имеет возвращаемые типы гипотетических вызовов, разрешенных компилятором.)

Нам нужно исследовать хотя бы одну и не более двух точек информации:

  • Существует ли вообще T::operator*()? Если нет, мы закончили.
  • Учитывая, что существует T::operator*(), является ли его подпись E T::operator*() const?

Мы получаем ответы, оценивая возвращаемый тип один вызов test(0,0). Это делается с помощью:

    typedef decltype(test(0,0)) type;

Этот вызов может быть разрешен в /* SFINAE operator-exists :) */ перегрузке test(), или он может решить перегрузку /* SFINAE game over :( */. Он не может решить перегрузку /* SFINAE operator-has-correct-sig :) */, потому что тот ожидает только один аргумент, и мы проходим два.

Почему мы проходим два? Просто заставить разрешение исключить /* SFINAE operator-has-correct-sig :) */. Второй аргумент не имеет никакой другой значимости.

Этот вызов test(0,0) разрешит /* SFINAE operator-exists :) */, если первый аргумент 0 удовлетворяет первому типу параметра этой перегрузки, который является decltype(&A::operator*), с A = T. 0 будет удовлетворять этому типу на всякий случай T::operator*.

Предположим, что компилятор говорит «Да». Затем это происходит с /* SFINAE operator-exists :) */, и ему нужно определить тип возврата вызова функции, который в этом случае decltype(test(&A::operator*)) - тип возврата еще одного вызова test().

На этот раз , мы передаем только один аргумент, &A::operator*, который мы теперь знаем, или мы не были бы здесь. Вызов test(&A::operator*) может разрешить либо /* SFINAE operator-has-correct-sig :) */, либо снова, чтобы разрешить /* SFINAE game over :( */. Вызов будет соответствовать /* SFINAE operator-has-correct-sig :) */ на всякий случай, если &A::operator* удовлетворяет типу одного параметра этой перегрузки, который E (A::*)() const, с A = T.

Компилятор скажет «Да», если T::operator* имеет эту желаемую подпись, а затем снова должен оценивать возвращаемый тип перегрузки. Больше нет «рекурсий»: это std::true_type.

Если компилятор не выбирает /* SFINAE operator-exists :) */ для вызова test(0,0) или не выбирает /* SFINAE operator-has-correct-sig :) */ для вызова test(&A::operator*), тогда в любом случае он идет с /* SFINAE game over :( */, а конечным типом возврата является std::false_type.

Вот тестовая программа, в которой показан шаблон, который дает ожидаемые ответы в разнообразной выборке случаев (GCC 4.6.3 снова ).

// To test
struct empty{};

// To test 
struct int_ref
{
    int & operator*() const {
        return *_pint;
    }
    int & foo() const {
        return *_pint;
    }
    int * _pint;
};

// To test 
struct sub_int_ref : int_ref{};

// To test 
template
struct ee_ref
{
    E & operator*() {
        return *_pe;
    }
    E & foo() const {
        return *_pe;
    }
    E * _pe;
};

// To test 
struct sub_ee_ref : ee_ref{};

using namespace std;

#include 
#include 
#include 

int main(void)
{
    cout << "Expect Yes" << endl;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op::iterator,int &>::value;
    cout << has_const_reference_op::const_iterator,
            int const &>::value;
    cout << has_const_reference_op::value;
    cout << has_const_reference_op::value  << endl;
    cout << "Expect No" << endl;
    cout << has_const_reference_op::value;
    cout << has_const_reference_op,char &>::value;
    cout << has_const_reference_op,int const &>::value;
    cout << has_const_reference_op,int>::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op,int &>::value;
    cout << has_const_reference_op::value;
    cout << has_const_reference_op::value  << endl;
    return 0;
}

Есть ли новые недостатки в этой идее? Может ли он стать более общим без лишних падений, чтобы избежать этого?

6
задан Nizam 19 December 2013 в 18:41
поделиться

2 ответа

Это - эффект новой возможности в Vista под названием "Упаковка": Windows имеет несколько механизмов, которые позволяют пользователю/администратору настраивать приложения для автоматического выполнения, когда окна запускаются. Эта функция главным образом используется для одной из этих целей: 1. Программы, которые являются частью основной рабочей среды пользователя, такого, что первое действие пользователь обычно брало бы при запуске компьютера, должны запустить их. 2. Все виды фона "агенты" - скайп, средство рассылки, winamp и т.д.

Когда слишком многие (или слишком тяжелый) программы регистрируются для работы запуска, конечный результат состоит в том, что пользователь ничего не может на самом деле сделать в течение первых нескольких секунд/минуты после входа в систему, который может быть действительно раздражающим. В прибывает функция "Boxing" Vista:

Кратко, Vista вынуждает все программы, вызванные через ключ Выполнения работать в низком приоритете в течение первых 60 секунд после входа в систему. Это влияет на оба приоритета ввода-вывода (который установлен на Очень Низкий), и приоритет ЦП. Очень Низкий приоритет запросы ввода-вывода не проходит через кэш файла, но переходит непосредственно к диску. Таким образом они намного медленнее, чем регулярный ввод-вывод. Продолжительность периода упаковки установлена значением реестра: "HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\DelayedApps\Delay_Sec".

Поскольку более подробное объяснение видит здесь и здесь

6
ответ дан 17 December 2019 в 02:36
поделиться

Для программы, вероятно, нужна еще некоторая информация, помещенная в ее свойства. Это должно "Работать Как" вместо просто выполнения.

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

0
ответ дан 17 December 2019 в 02:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: