重载方法的方式会在使用临时调用时生成编译器错误
Overload a method in a way that generates a compiler error when called with a temporary
也许这段代码最能说明我的意图:
#include <array>
template <size_t N>
void f(std::array<char, N> arr)
{
}
template <size_t N>
void f(std::array<char, N>&& arr)
{
static_assert(false, "This function may not be called with a temporary.");
}
f()
应该为左值而不是为右值编译。此代码适用于MSVC,但GCC在static_assert
上跳闸,即使从未调用此重载。
因此,我的问题有两个:如何用现代C++正确地表达我的意图,以及为什么编译器在从未实例化的"死"模板重载中评估static_assert
?
在线试用:https://godbolt.org/z/yJJn7_
一个选项是删除static_assert
,而将函数标记为已删除。然后,如果你用右值调用它,你会得到一个错误,说你试图使用一个已删除的函数
template <size_t N>
void f(const std::array<char, N>& arr)
{
}
template <size_t N>
void f(const std::array<char, N>&& arr) = delete; // used const here just in case we get a const prvalue
int main()
{
std::array<char, 3> foo{};
f(foo);
//f(std::array<char, 3>{}); // error
return 0;
}
足够简单。
template <size_t N>
void f(const std::array<char, N>&& arr) = delete;
只使用一个引用非常量对象的函数是可能的:
template<size_t N> void f(std::array<char, N>& arr);
不再需要过载。
此规则由语言规范强制执行但是Visual C++编译器有一个扩展,允许将右值传递给这样的函数。
除了其他答案之外,我想注意的是,标准库中有一个示例与OP想要的完全对应-std::addressof
:
template<class T>
constexpr T* addressof(T&) noexcept;
template<class T>
const T* addressof(const T&&) = delete;
相关文章:
- C++模板类 - 继承调用错误的函数
- 派生类调用父类的方法,该方法调用重写的虚拟方法调用错误的方法
- 使用 std::find 时没有匹配的函数调用错误
- 使用成员初始值设定项列表时没有匹配的函数调用错误
- C++调用错误签名的函数
- C++ 类成员调用错误 C3861
- C bool表达式作为函数参数调用错误的超载
- C ++尝试访问映射中的元素会给我一个不匹配的函数调用错误
- 当提供巨大的输入时,中止在堆栈操作程序中调用错误
- C++类静态成员函数调用错误
- 如何调查随机安卓原生函数调用错误?
- 引发实例后终止调用 - C++错误
- 如何修复传递参数时调用错误函数的主函数?(C++)
- 没有用于调用错误的匹配函数.将字符串推送到向量中
- 从括号内的initializer_list构造时,将调用错误的过载
- 为什么初始值设定项列表中的元素数会导致不明确的调用错误
- VC 15调用错误的复制构造函数以捕获lambda
- 在 C++ 中没有针对调用错误的匹配函数
- C++:函数调用错误:标识符"name"未定义,如果已定义?
- 为什么 GCC 在显式指定模板参数时会产生奇怪的错误并尝试调用错误的方法?