例如,我想要一个auto
类型的变量,因为我不确定它是什么类型。
当我尝试在class / struct声明中声明它时,它给了我这个错误:
无法推断自动类型。需要初始化程序
有办法吗?
struct Timer {
auto start;
};
答案 0 :(得分:23)
您可以,但必须声明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)};
}
答案 1 :(得分:4)
这是C++ draft standard在auto
段7.1.6.4 auto specifier
部分中使用4
成员变量时所说的内容:
auto-type-specifier也可用于在选择语句(6.4)或迭代语句(6.5)的条件中声明变量,在new-type-id或type中的type-specifier-seq中-id of一个新表达式(5.3.4),在for-range-declaration中,声明一个静态数据成员,其中一个括号或等于初始化程序出现在一个类的成员规范中定义(9.4.2)。
由于必须初始化,这也意味着它必须是const
。所以像下面这样的东西会起作用:
struct Timer
{
const static int start = 1;
};
我认为这不会让你太过分。使用模板作为马克建议或现在我想到它可能你只需要一个variant type。在这种情况下,您应该查看Boost.Variant
或Boost.Any
。
答案 2 :(得分:1)
没有。每个构造函数都可以拥有自己的start
初始化程序,因此可能没有一致的类型可供使用。
如果你做有一个可用的表达式,你可以使用:
struct Timer {
Foo getAFoo();
delctype(Timer().getAFoo().Bar()) start;
Timer() : start(getAFoo().Bar()) { /***/ }
};
答案 3 :(得分:0)
间接提供,前提是您不引用该类的成员。
现在也可以通过演绎指南来实现,它们是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的方式推断类成员类型。尽管成员变量需要以某种方式依赖于构造函数参数。