例如,我想要一个类型的变量,auto
因为我不确定它将是什么类型。
当我尝试在类/结构声明中声明它时,它给了我这个错误:
无法推断自动类型。需要初始化器
有办法解决吗?
struct Timer {
auto start;
};
你可以,但你必须声明它static
并且const
:
struct Timer {
static const auto start = 0;
};
由于此限制,因此您不能将start
其作为非静态成员,并且不能在不同的对象中具有不同的值。
如果您想start
为不同的对象使用不同的类型,最好将您的类作为模板
template<typename T>
struct Timer {
T start;
};
如果要推断 的类型T
,可以制作一个类似工厂的函数来进行类型推断。
template<typename T>
Timer<typename std::decay<T>::type> MakeTimer(T&& startVal) { // Forwards the parameter
return Timer<typename std::decay<T>::type>{std::forward<T>(startVal)};
}
这是C++ 标准草案在段落段落中关于使用auto
成员变量的内容:7.1.6.4 auto specifier
4
auto 类型说明符也可用于在选择语句 (6.4) 或迭代语句 (6.5) 的条件中声明变量,在 new-type-id 或 type-id 的 type-specifier-seq 中一个新表达式 (5.3.4),在一个 for-range-declaration 中,以及在声明一个带有大括号或相等初始化器的静态数据成员,该初始化器出现在类定义的成员规范中 (9.4.2) .
由于它必须被初始化,这也意味着它必须是const
. 所以像下面这样的东西会起作用:
struct Timer
{
const static int start = 1;
};
我不认为这让你得到太多。像 Mark 建议的那样使用模板,或者现在我想多了,也许你只需要一个变体类型。在这种情况下,您应该检查Boost.Variant
或Boost.Any
。
如果您在 lambda 表达式中声明一个类,您可以使用以下方法推断成员变量的类型decltype
:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
auto generic_class = [](auto width1, auto height1) {
class local_class {
public:
decltype(width1) width;
decltype(height1) height;
} local;
local.width = width1;
local.height = height1;
return local;
};
int main()
{
auto obj1 = generic_class(3,std::string("Hello!"));
auto obj2 = generic_class(std::vector<int>{1,2},true);
cout << obj1.height << "\n";
cout << obj2.width[0] << "\n";
return 0;
}
不可以。每个构造函数都可以有自己的初始化器start
,因此不能使用一致的类型。
如果你确实有一个可用的表达式,你可以使用它:
struct Timer {
Foo getAFoo();
delctype(Timer().getAFoo().Bar()) start;
Timer() : start(getAFoo().Bar()) { /***/ }
};
间接地,前提是您不引用该类的成员。
这现在也可以通过演绎指南来实现,这些是在 C++17 中引入的,并且最近(最终)添加了对 VC++ 的支持(clang 和 GCC 已经有了它)。
https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
例如:
template <typename>
struct CString;
template <typename T, unsigned N>
struct CString<std::array<T, N>>
{
std::array<T, N> const Label;
CString(std::array<T, N> const & pInput) : Label(pInput) {}
};
template <typename T, std::size_t N>
CString(std::array<T, N> const & pInput) -> CString<std::array<T, N>>;
这可以用于以与 auto 类似的方式推断类成员类型。尽管成员变量需要以某种方式依赖于构造函数参数。