考虑下面粘贴的代码。我已经定义了一个非常简单的类,编译器为其生成一个隐式推理指南,因此可以在没有显式模板参数的情况下构造它。但是,模板参数推导不能用于从简单的别名模板构造对象,该模板只能直接转发到目标类:
template< typename A, typename B >
struct Foo {
Foo( A const &a, B const &b )
: a_(a), b_(b)
{ }
A a_;
B b_;
};
template< typename A, typename B >
using Bar = Foo<A, B>;
auto foobar() {
Foo r{1, 2};
Bar s{3, 4};
// ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
// ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
// Bar s{3, 4};
// ^
return 1;
}
从上面的代码注释中可以看出,g ++在使用没有模板参数的别名模板时给出了错误。我希望在这样的实例中转发模板参数推导。
那么,我的问题:这是通过明确设计当前用于类模板参数推理的提案的措辞吗?或者这是该功能的当前g ++实现中未完成的功能或错误?对于提案的作者或C ++ ISO委员会来说,这将是一个更大的问题,但如果其中任何一个人看到这一点:是否希望该功能的最终措辞包括启用别名模板,例如是否为他们生成了隐含指南?
我可以理解,因为别名模板可以有任何类型的模板参数,编译器可能无法总是成功地推断出目标类模板参数,但在这种情况下,我希望编译器能够与它可以直接用于目标类的方式相同。
我使用--std=c++1z
在几天前使用gcc构建的gcc构建。完整版本信息为:gcc version 7.0.0 20161201 (experimental) (Homebrew gcc HEAD- --with-jit)
答案 0 :(得分:30)
这是我们在制定提案时考虑的一项功能,但它最终被削减,因为我们还没有足够好的设计。特别是,关于如何从别名模板中选择和转换演绎指南到别名模板的演绎指南,有一些细微之处。如果别名模板不是另一个模板的简单别名,那么还有一些关于如何表现的问题。一些例子:
template<typename T> struct Q { Q(T); }; // #1
template<typename T> struct Q<T*> { Q(T); }; // #2
template<typename T> using QP = Q<T*>;
int *x;
Q p = x; // deduces Q<int*> using #1, ill-formed
QP q = x; // deduces Q<int*> using #1, or
// deduces Q<int**> using #2?
template<typename T> Q(T) -> Q<T>; // #3
QP r = x; // can we use deduction guide #3 here?
template<typename T> Q(T*) -> Q<T**>; // #4
int **y;
QP s = y; // can we use deduction guide #4 here?
template<typename T> struct A { typedef T type; struct Y {}; };
template<typename T> using X = typename A<T>::type;
template<typename T> using Y = typename A<T>::Y;
X x = 4; // can this deduce T == int?
Y y = A<int>::Y(); // can this deduce T == int?
上述问题有很好的答案,但解决这些问题会增加复杂性,似乎最好不要推断C ++ 17的别名模板,而不是匆匆搞砸。
我预测我们会看到Faisal的一篇论文为C ++ 20提出这个功能。
答案 1 :(得分:2)
从http://en.cppreference.com/w/cpp/language/template_argument_deduction开始,“永远不会推断出别名模板。”所以,它是设计的。