Argumentos padrão do modelo

151

Se eu puder fazer o seguinte:

template <typename T = int>
class Foo{
};

Por que não estou autorizado a fazer o seguinte em principal?

Foo me;

Mas devo especificar o seguinte:

Foo<int> me;

O C ++ 11 introduziu argumentos de modelo padrão e, no momento, eles estão sendo esquivos para meu entendimento completo.

user633658
fonte

Respostas:

188

Você tem que fazer:

Foo<> me;

Os argumentos do modelo devem estar presentes, mas você pode deixá-los vazios.

Pense nisso como uma função foocom um único argumento padrão. A expressão foonão chamará isso, mas foo()sim. A sintaxe do argumento ainda deve estar lá. Isso é consistente com isso.

Joseph Mansfield
fonte
4
@Pubby Suponho que iria criar algumas complicações desnecessárias se Foo pode ser um identificador modelo ou pode ser uma instanciação explícita, dependendo se há um argumento padrão. Melhor manter a sintaxe de instanciação explícita. Pense nisso como uma função foocom um único parâmetro padrão. Você não pode chamá-lo assim foo, você pode chamá-lo com foo(). Faz sentido manter isso consistente.
31713 Joseph Mansfield
2
@sftrabbit mas você também não pode chamar uma função sem argumentos como foo; você pode nomear uma classe sem argumentos, Foono entanto.
Seth Carnegie
4
@aschepler Com uma função, os argumentos do modelo podem ser deduzidos dos argumentos da função. Com uma classe, não é possível decidir se você quis dizer uma classe de modelo com argumentos padrão ou uma classe que não é modelo.
Olaf Dietsche
21
@OlafDietsche, mas você não pode ter uma classe de modelo e uma classe que não seja de modelo com o mesmo nome; portanto, o compilador deve poder decidir apenas olhando para qual é o nome.
Seth Carnegie
7
@Pubby O comitê padrão se perguntou o mesmo, eu acho. Agora, com o C ++ 17, <>não é mais necessário neste caso. Confira minha resposta para mais detalhes.
Paolo M
53

Com o C ++ 17, você pode realmente.

Esse recurso é chamado dedução de argumento do modelo de classe e adiciona mais flexibilidade à maneira como você pode declarar variáveis ​​de tipos de modelo .

Assim,

template <typename T = int>
class Foo{};

int main() {
    Foo f;
}

agora é código C ++ legal .

Paolo M
fonte
5
Estranho. Apenas tentei no meu projeto C ++ 17 e não funcionou: "o tipo de espaço reservado para o modelo 'const MyType' deve ser seguido por um simples declarador-id". Estou usando o GCC 7.3.0.
Silicomancer
1
@ Silicomancer É difícil dizer sem ver seu código e linha de comando ... Talvez você esteja lidando com ponteiros como aqui ?
Paolo M
1
Clang não aceita isso parece? coliru.stacked-crooked.com/a/c5d3c0f90ed263c2
Borgleader:
1
@Borgleader Aparentemente, Coliru está usando o clang 5.0. A julgar por isso , ele deve suportar a dedução de argumento do modelo C ++ 17, mas evidentemente o id não. Se você tentar o mesmo exemplo no wandbox usando o clang 7.0, ele funcionará perfeitamente.
Paolo M
2
@ PaoloM Oh legal, fico feliz em saber que é apenas um problema de versão do compilador. Obrigado por analisar isso.
Borgleader
19

Você não tem permissão para fazer isso, mas você pode fazer isso

typedef Foo<> Fooo;

e então faça

Fooo me;
g24l
fonte
existe alguma diferença nisso com um tipo padrão e:, typedef Foo<float> Fooo;sem um tipo padrão?
Qrikko 30/05
5
A maneira C ++ 11-ish seria dizerusing Fooo = Foo<>;
Adrian W
18

Você pode usar o seguinte:

Foo<> me;

E tenha intseu argumento de modelo. Os colchetes angulares são necessários e não podem ser omitidos.

Andy Prowl
fonte
Faz sentido e obrigado, mas, como observado abaixo, por que o tipo especificado não está presente?
user633658
@ user633658: Você quis dizer "especificador de tipo"? Eu não tenho certeza se entendi
Andy Prowl
De qualquer forma, com relação à razão por trás da necessidade de colchetes angulares vazios, só posso fazer conjecturas, e é tudo sobre descartar possíveis ambiguidades apenas com o uso do nome do modelo, mas tenho que confessar que não sei exatamente motivo #
Andy Prowl
Eu suspeito fortemente que o requisito para <> seja permitir que o analisador do compilador determine que você está se referindo a uma classe de modelo chamada foo, em vez de outra coisa chamada foo.
Mac