使用std::decay和std::forward

3
template<typename T>
struct test
{
    std::string key;
    T value;
    
    template<typename U>
    using decay = typename std::decay<U>::type;

    template<typename U = decay<T>, typename US = decay<std::string>>
    test(U&& _value, US&& _key) : value(std::forward<U>(_value)), key(std::forward<US>(_key)){}
};

我在几乎每个项目中都使用衰减。我想问一下,这样做是否是一个好的选择,而不是像这样编写代码:
test(T&& _value, std::string&& _key) : value(std::move(_value)), key(std::move(_key)){}
test(const T& _value, std::string&& _key) : value(_value), key(std::move(_key)){}
test(T&& _value, const std::string& _key) : value(std::move(_value)), key(_key){}
test(const T& _value, const std::string& _key) : value(_value), key(_key){}

这有什么意义吗?你不能只保留模板构造函数,去除默认值和 decay 吗? - super
2个回答

3
你想得太多了,你只需要这个:
template<typename T>
struct test
{
    std::string key;
    T value; // as a safety this could be replaced by:
    // typename std::decay<T>::type value;
    
    template<typename U, typename US>
    test(U&& _value, US&& _key)
       : value(std::forward<U>(_value))
       , key(std::forward<US>(_key))
    {}
};

这种完美转发将确保您列出的所有构造函数都可用。

看起来你不理解 std::decay 的作用,或者何时/如何使用它。 例如:decay<std::string> 是没有意义的,因为这只代表了 std::string 类型,所以你应该直接写 std::string,你不需要进行任何转换,因为你对传递给 decay 的类型有完全控制,你知道这个类型不包含引用或常量,因为你明确地指定了这个类型。

std::decay 用于定义可以赋值的类型变量/字段。它去掉了引用和常量性,并将C数组转换为指针,并确保指向函数的指针。详见文档示例。

你能解释一下你打算通过默认模板参数类型实现什么计划吗?我无法理解你的意图是什么。


我不知道我可以在template<typename U, typename US>中不使用std::decay,这就是为什么我对模板参数使用默认类型的原因。在这个例子中,你认为我可以像template<typename T,typename U = typename std::decay<T>::type>这样做,并且有U值,或者这是无意义的? - Wojciech Xxx
默认模板参数类型在编译器无法推断类型时非常有用,因此当没有相应的参数或可能存在默认值的参数时,它们就会派上用场。 - Marek R

1

如果两个值实际上都保留在您的类内部,那么这要简单得多:

test(T value, std::string key)
    : value(std::forward<T>(value)), key(std::move(key)) {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接