std :: vector etc不必要(错误地?)实例化嵌套模板参数类型

Hui*_*Hui 5 c++ templates language-lawyer c++11

下面的代码编译得很好,即使很难std::plus<void>也是非法的(在C++ 11中).

template < typename > struct data {};
data<std::plus<void>> x; // does not attempt to complete std::plus<void>
Run Code Online (Sandbox Code Playgroud)

这是有道理的,因为data<std::plus<void>>不需要实例化std::plus<void>.但是,它在构造a时无法编译std::vector,这会以某种方式导致实例化std::plus<void>.

std::vector<data<std::plus<void>>> v;
Run Code Online (Sandbox Code Playgroud)

错误是:

/opt/local/libexec/llvm-3.5/bin/../include/c++/v1/functional:496:29: error: cannot form a reference to 'void'
_Tp operator()(const _Tp& __x, const _Tp& __y) const
/opt/local/libexec/llvm-3.5/bin/../include/c++/v1/type_traits:2055:27: note: in instantiation of
template class 'std::__1::plus<void>' requested here
decltype(__is_constructible_test(declval<_Tp>(), declval<_Args>()...))
Run Code Online (Sandbox Code Playgroud)

g ++ 4.8上的类似错误std::list.

这是预期的行为吗?

Col*_*mbo 3

\n

下面的代码编译得很好,即使很难编译std::plus<void>也是非法的(在 C++11 中)。

\n
\n\n

由于 C++1y 标准保证了以下显式专业化:

\n\n
template <> struct plus<void> {\n    template <class T, class U> constexpr auto operator()(T&& t, U&& u) const\n    -> decltype(std::forward<T>(t) + std::forward<U>(u));\n\n    typedef unspecified is_transparent;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

void实际上不完整的模板参数(如C++11 中的模板参数)的问题std::plus是:

\n\n
\n

特别是,在以下情况下效果未定义:

\n\n

\xe2\x80\x94 如果在实例化模板组件时使用不完整类型 (3.9) 作为模板参数,除非对该组件特别允许。

\n
\n\n

您的程序遇到未定义行为的原因是std::plus实例化的void类型不完整。

\n\n

写作的原因

\n\n
std::plus<void> p;\n
Run Code Online (Sandbox Code Playgroud)\n\n

不会导致编译器错误(同时导致UB)的原因是模板的成员函数在使用之前不会被实例化

\n