O seguinte é um exemplo de brinquedo
A classe student
tem um std::array<char, 15>
chamado name
e um inteiro age
. Um aluno tem uma função membro chamada encode
que chama uma função de modelo global encode
usando name.size()
como parâmetro de modelo.
O código é mostrado abaixo:
//main.cpp
#include <iostream>
#include <array>
template <unsigned long num1>
unsigned long encode(unsigned long num2){
return num1 + num2;
}
struct student {
std::array<char, 15> name;
int age;
student(const std::array<char, 15>& name, int age):
name(name),
age(age)
{}
unsigned long encode(){
return ::encode<name.size()>(age);
}
};
int main(){
std::array<char, 15> name = {"Tim"};
student Tim(name, 17);
std::cout << Tim.encode();
}
No entanto, isso produz o seguinte erro do compilador
>g++ main.cpp -std=c++11
main.cpp: In member function 'long unsigned int student::encode()':
main.cpp:22:43: error: use of 'this' in a constant expression
22 | return ::encode<name.size()>(age);
| ^
main.cpp:22:45: error: no matching function for call to 'encode<((student*)this)->student::name.std::array<char, 15>::size()>(int&)'
22 | return ::encode<name.size()>(age);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:9:15: note: candidate: 'template<long unsigned int num1> long unsigned int encode(long unsigned int)'
9 | unsigned long encode(unsigned long num2){
| ^~~~~~
main.cpp:9:15: note: template argument deduction/substitution failed:
main.cpp:22:45: error: use of 'this' in a constant expression
22 | return ::encode<name.size()>(age);
| ~~~~~~~~~~~~~~~~~~~~~^~~~~
main.cpp:22:42: note: in template argument for type 'long unsigned int'
22 | return ::encode<name.size()>(age);
É necessário que eu faça isso ::encode<15>(age)
para resolver esse problema, porque eu acho que um dos principais benefícios de um std::array
é poder carregar um tamanho em vez de ter que armazenar o tamanho em alguma variável extra (ou codificar o tamanho).
g++ version: 14.1.0
Não gosto de incluir o
<tuple>
cabeçalho apenas para usarstd::tuple_size_v
.Acho que você também pode expressar o mesmo usando
decltype(name)
fornece o tipo, sem a necessidade dothis
ponteiro{}
cria uma instância.size()
fornece o tamanho dessa instânciaComo se trata de constexpr, ele é avaliado como 15 em tempo de compilação e não há sobrecarga real para a criação da instância temporária.
Você pode obter o valor de
N
do array usandostd::tuple_size<std::array>
algo como:Isso pode ser visto funcionando neste exemplo ao vivo .
O uso de
name.size()
require permite acessarthis
(e por meio dele o membroname
), mas isso não compila porque este não é um contexto constexpr.Em vez disso, você deve usar o tipo do
std::array
name
que já implica o tamanho.Para isso, você pode usar
std::tuple_size
(que tem uma especialização parastd::array
),possivelmente com sua variável auxiliar template
std::tuple_size_v
:Observe o uso de
decltype
para obter o tipo dostd::array
membroname
.Demonstração ao vivo .