是否可以拥有“自动”成员变量?

时间:2013-08-13 02:31:33

标签: c++ struct auto

例如,我想要一个auto类型的变量,因为我不确定它是什么类型。

当我尝试在class / struct声明中声明它时,它给了我这个错误:

  

无法推断自动类型。需要初始化程序

有办法吗?

struct Timer {

    auto start;

};

4 个答案:

答案 0 :(得分:23)

您可以,但必须声明staticconst

struct Timer {
    static const auto start = 0;
};

A working example in Coliru

有了这个限制,您就不能将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)};
}

Live example

答案 1 :(得分:4)

这是C++ draft standardauto7.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.VariantBoost.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>>;

https://godbolt.org/z/LyL7UW

这可用于以类似于auto的方式推断类成员类型。尽管成员变量需要以某种方式依赖于构造函数参数。