你可能会说我应该没事了
std::is_lvalue_reference<T>::value
但是当字符串文字出现问题时会出现问题。正如我所读到的,字符串文字被视为const char *,它被评估为左值。如何确保字符串文字将被视为右值?
假设以下不存在的代码。
template <typename T>
inline static void f(T&& arg) {
static_assert(my_lvalue_traits<T>::value, "Only lvalue permitted") ;
// Some code.
}
如果我想实现这些结果,my_lvalue_traits应该如何?
std::string x;
f(x); // Everything OK, the argument is an lvalue.
int y;
f(y); // Everything OK, the argument is an lvalue.
f("some literal"); // Static assertion failure. I want string literal to behave as an rvalue.
f(5); // Static assertion failure. Argument is an rvalue.
请注意,我想在一个可变模板类中使用这个特性,所以这可能不是一个完美的例子。像
这样的东西f(std::string("some literal"));
也不是解决方案。
答案 0 :(得分:1)
字符串文字不是 完全 a const char *
。您可以使用专业化来利用这一点。
使用gcc 7.3.1进行测试:
#include <type_traits>
#include <utility>
#include <functional>
template<typename T>
inline static void f(T&& arg) {
static_assert(std::is_lvalue_reference_v<T>, "Only lvalue permitted");
}
template<size_t n>
inline static void f(const char (&arg)[n])
{
static_assert(n!=n, "Only lvalue permitted");
}
int main()
{
std::string x;
f(x); // ok
int y;
f(y); // ok
const char *p;
f(p); // ok
f("foobar"); // fail
return 0;
}
答案 1 :(得分:1)
A string literal is an lvalue。所以你不能只将字符串文字视为rvalues,而这并不是你想要的 - 你想要排除字符串文字。
这样做的一种方法是删除右值const char*
重载:
template <typename T>
void foo(T&& ) {
static_assert(std::is_lvalue_reference_v<T>);
}
void foo(const char*&& ) = delete;
调用foo("wat")
更喜欢第二个(见this question),所以这实际上排除了它们(虽然字符串文字本身是一个左值,它衰变的指针是一个右值 - 所以它可以绑定到右值参考)。
但请注意,这也有效地排除了任何其他字符数组。
foo("hello"); // ill-formed, as desired
const char msg[] = "hello";
foo(msg); // also ill-formed, unfortunately
实际上没有办法解决这个问题,因为你无法在字符串文字和任何其他类型的字符数组之间区分(编辑:在模板推导期间的替换点)。