以下代码编译得很好,即使很难std::plus<void>
也是非法的(在C ++ 11中)。
template < typename > struct data {};
data<std::plus<void>> x; // does not attempt to complete std::plus<void>
这是有道理的,因为data<std::plus<void>>
不需要实例化std::plus<void>
。但是,它在构造std::vector
时无法编译,这会以某种方式导致std::plus<void>
的实例化。
std::vector<data<std::plus<void>>> v;
错误是:
/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>()...))
g ++ 4.8或std::list
上的类似错误。
这是预期的行为吗?
答案 0 :(得分:3)
以下代码编译得很好,即使是
std::plus<void>
也很难 非法的(在C ++ 11中)。
自C ++ 1以来,该标准保证了以下明确的专业化:
template <> struct plus<void> {
template <class T, class U> constexpr auto operator()(T&& t, U&& u) const
-> decltype(std::forward<T>(t) + std::forward<U>(u));
typedef unspecified is_transparent;
};
实际上不完整的模板参数(例如C ++ 11中void
的{{1}})的问题是:
特别是,在以下情况下效果未定义:
- 如果使用不完整类型(3.9)作为模板参数 实例化模板组件,除非特别允许 该组件。
您的程序遇到未定义行为的原因是std::plus
使用std::plus
实例化,这是一个不完整的类型。
写作的原因
void
不导致编译器错误(导致UB)是模板的成员函数在使用之前未实例化。