28

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

当我尝试在类/结构声明中声明它时,它给了我这个错误:

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

有办法解决吗?

struct Timer {

    auto start;

};
4

5 回答 5

31

你可以,但你必须声明它static并且const

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

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)};
}

活生生的例子

于 2013-08-13T02:33:34.287 回答
5

这是C++ 标准草案在段落段落中关于使用auto成员变量的内容:7.1.6.4 auto specifier4

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.VariantBoost.Any

于 2013-08-13T03:00:56.723 回答
2

如果您在 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;
}
于 2021-09-30T18:51:30.930 回答
1

不可以。每个构造函数都可以有自己的初始化器start,因此不能使用一致的类型。

如果你确实有一个可用的表达式,你可以使用它:

struct Timer {

   Foo getAFoo();

   delctype(Timer().getAFoo().Bar()) start;

   Timer() : start(getAFoo().Bar()) { /***/ }
};
于 2013-08-13T08:11:55.533 回答
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 类似的方式推断类成员类型。尽管成员变量需要以某种方式依赖于构造函数参数。

于 2018-09-17T03:45:06.373 回答