AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-10141210

Josh Shields's questions

Martin Hope
Josh Shields
Asked: 2025-01-19 14:55:55 +0800 CST

Por que std::vector<T> v{1, 2, 3} e std::vector<T> v = {1, 2, 3} chamam construtores diferentes, quando T converte implicitamente de int?

  • 12

Pergunta - veja Compiler Explorer

Se eu criar um std::vector<int>e inicializá-lo de duas maneiras, ambas chamarão o std::initializer_listconstrutor.

std::vector<int>  v1{1, 2, 3};     // Calls vector(initializer_list< int >)
std::vector<int>  v2 = {1, 2, 3};  // Calls vector(initializer_list< int >)

Mas se eu usar uma classe que converte implicitamente de int:

struct Imp { Imp(int) {} };

Então o segundo método de inicialização chama o construtor que recebe um par de iteradores.

std::vector<Imp>  v3{1, 2, 3};     // Calls vector(initializer_list< Imp >)
std::vector<Imp>  v4 = {1, 2, 3};  // Calls vector(const int*, const int* ) ???

Isso só acontece usando GCC 14.2 . Ao usar Clang 19.1 ou MSVC 19.40 , ambos v3e v4chamam o initializer_listconstrutor. O nível de otimização não faz diferença

Por que a = {}sintaxe chama vector(const int*, const int*)o GCC?

Investigação adicional

Tentei criar meu próprio modelo de classe que tem ambos os construtores:

template <typename T>
struct Custom {
    Custom(std::initializer_list<T>) {}
    Custom(const int*, const int*)   {}
};

Agora, tanto a sintaxe {}e = {}chamam o initializer_listconstrutor no GCC.

Custom<Imp>       v5{1, 2, 3};     // Calls Custom(initializer_list< Imp >)
Custom<Imp>       v6 = {1, 2, 3};  // Calls Custom(initializer_list< Imp >)


Onde as coisas ficam realmente confusas é se eu me especializo std::vectorpara meu tipo de conversão implícita Imp. Então há três casos:

Caso 1 - Fornecerinitializer_listapenas ctor

template <>
struct std::vector<Imp> {
    vector(initializer_list<Imp>)   {}
};

Resultado - Ambas as sintaxes chamam o ctor fornecido

std::vector<Imp> v7{1, 2, 3};      // Calls vector(initializer_list< Imp >)
std::vector<Imp> v8 = {1, 2, 3};   // Calls vector(initializer_list< Imp >)


Caso 2 - Fornecerconst int*apenas ctor

template <>
struct std::vector<Imp> {
    vector(const int*, const int*)   {}
};

Resultado - Ambas as sintaxes falham na compilação (nenhum ctor correspondente)

std::vector<Imp> v9{1, 2, 3};      // Error - no matching ctor
std::vector<Imp> vA = {1, 2, 3};   // Error - no matching ctor


Caso 3 - Forneça ambos os ctors

template <>
struct std::vector<Imp> {
    vector(initializer_list<Imp>)    {}
    vector(const int*, const int*)   {}
};

Resultado - A{}sintaxe chama oinitializer_listctor, enquanto a= {}sintaxe chama oconst int*ctor

std::vector<Imp> vB{1, 2, 3};      // Calls vector(initializer_list< Imp >)
std::vector<Imp> vC = {1, 2, 3};   // Calls vector(const int*, const int*) ???

É aqui que estou perdido.

No caso 3 , como fornecer o initializer_listconstrutor permite que o const int*construtor seja chamado?

EDITAR

Perguntaram como eu sei qual construtor está sendo chamado. Isso começou quando eu estava olhando quando os construtores copy vs. move são chamados. std::initializer_listnão pode ser movido de. Mas aqui estão alguns exemplos adicionais, com prints.

Exemplo 1 - Usando um tipo autônomo

struct Imp { Imp(int) {} };

template <typename T>
struct Custom {
    Custom(std::initializer_list<T>)    { std::printf("initializer_list<T>\n");    }
    Custom(const int*, const int*)      { std::printf("const int*, const int*\n"); }
};

int main(int argc, char *argv[]) {
    Custom<Imp>     v{1, 2, 3};
    Custom<Imp>     w = {1, 2, 3};

Impressões:

initializer_list<T>
initializer_list<T>

Exemplo 2 - Usando uma especialização std::vector

struct Imp { Imp(int) {} };

template <>
struct std::vector<Imp> {
    vector(initializer_list<Imp>)       { std::printf("initializer_list<T>\n");    }
    vector(const int*, const int*)      { std::printf("const int*, const int*\n"); }
};

int main(int argc, char *argv[]) {
    std::vector<Imp>    v{1, 2, 3};
    std::vector<Imp>    w = {1, 2, 3};

Impressões:

initializer_list<T>
const int*, const int*

A única diferença entre os dois exemplos é que um é uma especialização std:: e o outro não.

Por que isso mudaria qual sobrecarga de ctor é chamada?

c++
  • 1 respostas
  • 387 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve