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 / coding / Perguntas / 79287963
Accepted
Andrea Agostini
Andrea Agostini
Asked: 2024-12-17 20:57:10 +0800 CST2024-12-17 20:57:10 +0800 CST 2024-12-17 20:57:10 +0800 CST

Declarações repetidas de um modelo com um parâmetro de tipo-modelo definido como padrão para um tipo de fechamento são uma violação do ODR?

  • 772

Como o C++20 nos deu lambdas em contexto não avaliado, posso escrever o seguinte código.

template <class = decltype([]{})>
class MyType {};

Se eu incluísse essa definição em várias TUs, isso seria uma violação do ODR?

Estou analisando em particular o §6.3(13.13) do N4860:

Em cada uma dessas definições, [...] um argumento de modelo padrão usado por um template-id (implícito ou explícito) ou simple-template-id é tratado como se sua sequência de tokens estivesse presente na definição de D; ou seja, o argumento padrão ou argumento de modelo padrão está sujeito aos requisitos descritos neste parágrafo (recursivamente).

que eu li como, decltype([]{})é parte do tipo declarado, que é então um exemplo explicitamente rotulado como inválido pelo artigo original (§4). Estou lendo isso corretamente?

Edição 1: aqui está outra citação do mesmo parágrafo do padrão que considero muito confusa:

Pode haver mais de uma definição de uma
[...]
(13.4) — entidade modelo (13.1),
[...]
(13.6) — argumento modelo padrão
em um programa, desde que cada definição apareça em uma unidade de tradução diferente e as definições satisfaçam os seguintes requisitos. Dada tal entidade D definida em mais de uma unidade de tradução, para todas as definições de D, [...] os seguintes requisitos devem ser satisfeitos.
[...]
(13.10) — Em cada uma dessas definições, exceto dentro dos argumentos padrão e argumentos modelo padrão de D, as expressões lambda correspondentes devem ter o mesmo tipo de fechamento (veja abaixo).

Agora, podemos aplicar este parágrafo ao meu trecho de código acima
a) tomando D como o modelo de classe (que é uma entidade modelo), em cujo caso (13.10) parece dizer que o argumento de modelo padrão está isento desta regra, ou
b) tomando D como o argumento de modelo padrão, ao qual esta regra deve ser aplicada. O "veja abaixo" no final da citação se refere, presumo, ao ponto 14:

Se D for um modelo e for definido em mais de uma unidade de tradução, os requisitos precedentes devem ser aplicados tanto aos nomes do escopo envolvente do modelo usados ​​na definição do modelo (13.8.3), quanto aos nomes dependentes no ponto de instanciação (13.8.2). Esses requisitos também se aplicam às entidades correspondentes definidas dentro de cada definição de D (incluindo os tipos de fechamento de expressões lambda, mas excluindo entidades definidas dentro de argumentos padrão ou argumentos de modelo padrão de D ou uma entidade não definida dentro de D). Para cada uma dessas entidades e para o próprio D, o comportamento é como se houvesse uma única entidade com uma única definição, incluindo na aplicação desses requisitos a outras entidades. [Nota: A entidade ainda é declarada em várias unidades de tradução, e 6.6 ainda se aplica a essas declarações. Em particular, as expressões lambda (7.5.5) que aparecem no tipo de D podem resultar em diferentes declarações tendo tipos distintos, e as expressões lambda que aparecem em um argumento padrão de D ainda podem denotar tipos diferentes em diferentes unidades de tradução. — nota final]

do qual eu entendo: se D é minha classe de modelo, o argumento de modelo padrão está isento desta regra. Mas então a nota no final continua especificando que a expressão lambda no argumento de modelo padrão pode ter tipos diferentes em TUs diferentes, portanto, presumo, quebrando ODR.

Edição 2: muito relacionado, mas ainda não consigo chegar a uma conclusão final:
Significado da observação sobre itens definidos várias vezes
As expressões lambda que aparecem em diferentes definições de uma mesma entidade produzem o mesmo tipo de fechamento?

c++
  • 1 1 respostas
  • 109 Views

1 respostas

  • Voted
  1. Best Answer
    Brian Bi
    2024-12-18T10:24:43+08:002024-12-18T10:24:43+08:00

    Sim, você obteria uma violação de ODR neste caso, e geralmente é IFNDR, exceto no caso de módulo nomeado mencionado em [basic.def.odr]/15.

    [basic.def.odr]/1.7 afirma que argumentos de modelo padrão são um dos tipos de item definível e [basic.def.odr]/15 requer múltiplas definições de um item definível para ser "o mesmo". Entretanto, cada expressão lambda produz um tipo distinto, incluindo o mesmo lambda escrito da mesma forma em duas unidades de tradução diferentes. Há situações em que um lambda tem o mesmo tipo em duas TUs porque ele é parte de uma definição envolvente:

    inline int foo() {
        return []{ return 0; }();  // same lambda in every TU
    }
    

    Isso ocorre somente porque [basic.def.odr]/17 permite que múltiplas definições de um item definível se comportem como se houvesse uma única definição no programa. No caso de foo, uma única definição em todas as TUs implica um único tipo de fechamento lambda em todas as TUs.

    Essa unificação se aplica ao modelo de classe do OP? Não, porque [basic.def.odr]/17 tem um carve-out para argumentos padrão e argumentos de modelo padrão:

    Esses requisitos também se aplicam a entidades correspondentes definidas dentro de cada definição de D(incluindo os tipos de fechamento de lambda-expressions , mas excluindo entidades definidas dentro de argumentos padrão ou argumentos de modelo padrão de Dou uma entidade não definida dentro de D). Para cada uma dessas entidades e para Dsi mesma, o comportamento é como se houvesse uma única entidade com uma única definição, incluindo na aplicação desses requisitos a outras entidades.

    Tomando Dcomo modelo de classe MyType, vemos que o argumento de modelo padrão para seu parâmetro de modelo (sem nome) é uma entidade excluída, então o comportamento não é como se houvesse apenas uma única definição do argumento padrão em todo o programa.

    Por outro lado, tomando Dcomo definição de argumento padrão, vemos que [basic.def.odr]/15 é violado porque o item 15.6 requer:

    Em cada uma dessas definições, exceto dentro dos argumentos padrão e argumentos de modelo padrão de , as expressões lambdaD correspondentes devem ter o mesmo tipo de fechamento (veja abaixo).

    Porque Dneste caso é o argumento de modelo padrão em si, ele não tem nenhum argumento de modelo padrão próprio ( Dafinal, não é um modelo em si), então não pode se beneficiar da exceção neste marcador. A expressão lambda deve ser a mesma em todas as definições. Porque /15 é violado, Dnão pode se beneficiar de /17, é apenas uma violação de ODR.

    Um dos exemplos na p18 usa um argumento de função padrão em vez de um argumento de modelo padrão:

    inline void g(bool cond, void (*p)() = []{}) {
      if (cond) g(false);
    }
    

    O texto explicativo afirma que definir gem múltiplas TUs causa uma violação de ODR porque cada lambda tem um tipo diferente. Como argumentos de função padrão são tratados da mesma forma que argumentos de modelo padrão para os propósitos do ODR, o exemplo do OP foi claramente concebido para também ser uma violação de ODR.

    • 4

relate perguntas

  • Por que os compiladores perdem a vetorização aqui?

  • Erro de compilação usando CMake com biblioteca [fechada]

  • Erro lançado toda vez que tento executar o premake

  • Como criar um tipo de octeto semelhante a std::byte em C++?

  • Somente operações bit a bit para std::byte em C++ 17?

Sidebar

Stats

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

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

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 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

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 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
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +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
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +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