问题描述
我想要一个仅绑定到一种类型的转发引用。我可以使用静态断言, 但我想知道是否有一种更优雅的(C ++ 14/17)方法来做到这一点。
这里有个例子:
#include <iostream>
#include <string>
#include <type_traits>
template<class T>
void f(T&& x) {
// Is there a more elegant way to check for the type than the static_assert?
static_assert(std::is_same<std::string,typename std::remove_cv_t<std::remove_reference_t<T>>>::value);
x = x + "Bar";
std::cout << x << std::endl;
}
int main()
{
std::string name("Foo");
f(name);
f(std::move(name));
}
解决方法
您可以使用std::enable_if
使用编译时检查,如下所示
template<class T>
std::enable_if_t<std::is_same_v<std::string,typename std::remove_cv_t<std::remove_reference_t<T>>>,void> f(T&& x) {
x = x + "Bar";
std::cout << x << std::endl;
}
如果您可以使用c ++ 20,则效果会更好,如下所示
template<class T>
void f(T&& x)requires(std::is_same_v<std::string,typename std::remove_cv_t<std::remove_reference_t<T>>>) {
x = x + "Bar";
std::cout << x << std::endl;
}
,
C ++ 20方法:
template <typename T>
requires std::same_as<std::string,std::remove_cvref_t<T>>
void f(T &&x) {}
C ++ 17方式:
template <
typename T,std::enable_if_t<
std::is_same_v<
std::string,std::remove_cv_t<std::remove_reference_t<T>>
>,std::nullptr_t
> = nullptr
>
void f(T &&x) {}
C ++ 14的方式与C ++ 17相同,除了必须使用std::same_as<...>::value
代替std::is_same_v
。
我也发现自己也遇到了这个问题,直到c ++ 20都还没有解决方案。
template<typename T>
concept StringRef = std::is_same<std::string,typename std::remove_cv_t<std::remove_reference_t<T>>>::value;
void f(StringRef auto &&x)
{
// ...
}