仅绑定一种类型的转发参考?

问题描述

我想要一个仅绑定到一种类型的转发引用。我可以使用静态断言, 但我想知道是否有一种更优雅的(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)
{
    // ...
}