Разрешить std :: string для чего-то другого, кроме :: std :: string - возможно ли это? - PullRequest
0 голосов
/ 11 октября 2019

Это дополнительный вопрос от: построение строки из NULL?

Следующее:

void test(const std::string& s);

int main(){
  test(NULL);
}

Сбой при запуске, но является допустимым c ++.

Чтобы попытаться отследить некоторые из этих случаев, в качестве альтернативы я рассмотрю, может ли std::string быть замененным в следующемway:

#include <string>


namespace {
namespace std {
    struct string : public ::std::string { //so far everything is good

    };
}
}


int main ()
 {
   std::string hello;//failure: ambiguous symbol

   return 0;
 }

Выдает следующую ошибку:

<source>(17): error C2872: 'std': ambiguous symbol

C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'

<source>(7): note: or       '`anonymous-namespace'::std'

<source>(17): error C2872: 'std': ambiguous symbol

C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'

<source>(7): note: or       '`anonymous-namespace'::std'

Compiler returned: 2

Я думаю, что невозможно разрешить его без написания более (полностью) квалифицированного имени? но возможно ли написать std :: string в глобальном пространстве имен и разрешить его в другое значение, тогда как :: std :: string является допустимым типом.

Справочная информация : после некоторых неудачных попыток проверки cppcheck и cpp core, я пытаюсь найти все случаи std::string str = 0 или NULL или nullptr - так как они не будут выполнены во время выполнения. И я подумал, что это может быть путь вперед.

Я закончил тем, что изменил шаблон Basic_string аля. basic_string(int) = delete; basic_string(::std::nullptr_t) = delete; - это не охватит все случаи, но, похоже, действительно учитывает прямые случаи, по крайней мере,

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Разрешить std::string к чему-то другому, чем ::std::string - возможно ли это? [...]... в качестве альтернативы я рассматриваю возможность замены std::string следующим образом ...

Насколько я знаю, это невозможно вне вашей анонимной области пространства имен потому что у вас нет способа разрешить неоднозначность (не в моих силах).

Как вы можете видеть ниже, поскольку вы находитесь внутри области анонимного пространства имен, все будет хорошо:

#include <string>

namespace
{
    namespace std
    {
        struct string : public ::std::string
        {

        };
    }
    std::string hello; // Fine
}


int main()
{
    std::string hello2; // Cannot be something else that ambiguous

    return 0;
}

Но, что еще хуже, проблема не в самом std::string, а в пространстве имен std.

Действительно, вне области вашего анонимного пространства имен, каждый вызовstd тоже становится двусмысленным. Это ошибка, указанная компилятором. Есть два std пространства имен, доступных как есть из глобальной области.

Таким образом, следующий пример становится неработоспособным:

#include <string>
#include <vector>

namespace
{
    namespace std
    {
        struct string : public ::std::string
        {

        };
    }
    std::string hello; // Fine
}


int main()
{
    std::vector<int> a; // FAIL: reference to 'std' is ambiguous

    return 0;
}

Чтобы исправить эту неоднозначность при доступе к исходному пространству имен std,вам нужно будет написать это следующим образом:

::std::vector<int> a; // Fully qualified name: Only way to refer to the `::std` namespace

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


Поэтому мораль такова:

  • Не скрывайте уже существующий тип, а вместо этого создайте отдельный.
  • Таким же образом, не скрывайте пространство имен (определяя одно и то же пространство имен в анонимное -> зло).

(I 'я открыт для любых предложений по улучшению этого ответа)

0 голосов
/ 11 октября 2019

Не могли бы вы использовать такое решение: вместо того, чтобы работать с std :: string, вы работаете с функцией, которая вызовет проблему

#include <string>

void test(const std::string& s){

}
// add a new function which use a pointer : 
void test (const char* _Nonnull s) {
    test(std::string(s));

}
int main()
{
    test(NULL);
    return 0;
}

Тогда clang выдаст предупреждение: 1 предупреждение сгенерировано.

ASM generation compiler returned: 0

<source>:13:14: warning: null passed to a callee that requires a non-null argument [-Wnonnull]

test(NULL);

см. https://godbolt.org/z/PujFor

...