1
template<typename T>
class A
{
    public:

    A(T &t)
    : t_(t){}

    T t_;
};


int main()
{
    int value;
    A<decltype(value)> a(value);
    // what I wish for : A a(value); 
    // which does not compile "missing template argument before 'a'"
}

有没有办法在 A (或其他地方)的声明中提示编译器 T 应该自动解析为传递给构造函数的类型?

(理想情况下是 c++11,但很高兴听到更少的旧版本)

4

3 回答 3

6

C++17 开箱即用(或借助演绎指南),以前的版本不能。

于 2020-02-15T12:35:20.570 回答
4

正如@Quentin 所回答的,这只能从 C++17 开始。但是,如果您可以调用函数来创建A对象,那么以下内容应该可以在 C++11 中执行您想要的操作:

template <class T, class NonRefT = typename std::remove_reference<T>::type>
A<NonRefT> create_A (T && t) {
  return A<NonRefT>(std::forward<T>(t));
}

// Or even closer to your original code:
template <class T>
auto create_A (T && t) -> A<decltype(t)> {
  return A<decltype(t)>(std::forward<T>(t));
}

我使用std::remove_reference的是基于您对 的使用decltype,尽管您可能想要使用它std::decay

int main () {
  int value = 5;
  auto a = create_A(value);
}

如果我没记错的话,示例代码有一个边缘情况,它在 C++17 之前不能按预期工作。编译器将省略复制/移动构造函数以acreate_A(). 但是,它会在编译期间检查A的复制/移动构造函数(它不会使用)是否可用/可访问。从 C++17 开始,复制/移动省略是“正确”完成的,此类代码不需要复制/移动构造函数。(另外,我可能记错了,它可能正在检查复制/移动分配。)

于 2020-02-15T12:47:20.510 回答
2

在 C++11 中,您可以创建一个简单的make_A函数,如下所示:

#include <iostream>

template <typename T>
class A {
public:
    A(T &t) : t_(t) {}

    T t_;
};

template <typename T>
A<T> make_A(T&& t) {
    return A<T>(std::forward<T>(t));
}

int main() {
    int value = 0;
    auto a = make_A(value);

    return 0;
}

演示

于 2020-02-15T13:03:17.093 回答