我想知道为什么这段代码不能编译,给出错误:不完整类型std :: tuple_size< aveure>用于嵌套名称说明符
如果函数与类型不匹配,甚至无法编译它,我希望会出现运行时错误。
#include <iostream>
#include <typeinfo>
#include <tuple>
struct aveure{
int que;
};
template<typename T>
void prova(T valor){
int s;
if (typeid( valor ) == typeid( aveure )) // Even having if (true)
// would cause the same error
s=valor.que;
else
s = std::tuple_size< T >::value; // ERROR !!! Even when T is a
// struct aveure, not a tuple
std::cout << s;
}
int main() {
aveure qui;
qui.que=2;
prova<aveure>(qui);
return 0;
}
当然,这个错误可以解决分裂功能:
#include <iostream>
#include <typeinfo>
#include <tuple>
struct aveure{
int que;
};
template< typename T >
int len(T val){
return( std::tuple_size< T >::value );
}
template<>
int len(aveure quan){
return quan.que;
}
template<typename T>
void prova(T valor){
int s = len(valor);
std::cout << s<<std::endl;
}
int main() {
aveure qui;
qui.que=2;
prova<aveure>(qui); // returns 2
auto first = std::make_tuple (10,'a',"hola");
prova<decltype(first)>(first); // returns 3
return 0;
}
有没有更好的解决方案来解决它?
答案 0 :(得分:0)
您无法编写类似的静态代码检查。使用C ++,函数中的每一行都必须是可编译的。在模板函数中,每一行必须对其调用的每种类型都有效。因此:
template <typename T>
void prova(T valor){
int s;
if (typeid( valor ) == typeid( aveure ))
s = valor.que; // valid ONLY for aveure
else
s = std::tuple_size< T >::value; // valid ONLY for std::tuple
std::cout << s;
}
结果,这个函数没有编译的希望。你可以做的只是为prova
提供两种不同情况的重载:
void prova(aveure valor) {
std::cout << valor.que;
}
template <typename... Args>
void prova(std::tuple<Args...> ) {
std::cout << sizeof...(Args);
}
或者你可以使用所谓的SFINAE。必须以编译器只编译一个或另一个分支并且仅针对有效类型的方式重构if语句。这是您的逻辑直接转换为:
template <typename T>
typename std::enable_if<
std::is_same<T, aveure>::value // T is an aveure
>::type
prova(T valor) {
std::cout << valor.que;
}
template <typename T>
typename std::enable_if<
!std::is_same<T, aveure>::value // else { ... }
>::type
prova(T valor) {
std::cout << std::tuple_size<T>::value;
}
答案 1 :(得分:0)
首先,类型未完全指定。你必须做类似的事情:
std::tuple<decltype(valor)> mytuple;
...
s = std::tuple_size<decltype(mytuple)>::value;
主要问题是: S = valor.que; 传递给prova(T)的每个类型名称T必须支持T :: que。 你不能用if-else来解决这个问题。
我想,既然你知道T的确切类型,你就可以逃脱:
s =((aveure *)&amp; valor) - &gt; que;
但不建议这样做。
最后,你可以添加一个强制转换操作符,而不用去解除引用: struct aveure { int que; operator int(){return que;} };
...
if (typeid( valor ).name() == typeid( aveure ).name())
s=valor; // no need for s=valor.que