c++ - 使用默认参数转发引用?

标签 c++ templates constructor default-arguments forwarding-reference

我在尝试弄清楚如何为转发引用(以前由 Scott Meyers 称为 Universal References)指定默认参数时遇到了问题。

下面是一个尝试做我想做的事情的代码示例:

struct encoder_t {

} const encoder = {};

struct validator_t {

} const validator = {};

struct test {

    template <typename Range, typename Encoding, typename Validation>
    test ( Range&& range, Encoding&& encoding = encoder, Validation&& validation = validator ) {

    }

};

int main() {

    test( "woof" );

}

Also available on Coliru .

通过错误,你发现你可以通过默认模板参数让它工作,然后默认构造参数:

// Works! But the syntax is strange... potential ramifications/deduction mishaps?
// Is this the "proper" way to default these arguments?
template <typename Range, typename Encoding = encoder_t, typename Validation = validator_t>
test ( Range&& range, Encoding&& encoding = Encoding(), Validation&& validation = Validation() ) {

}

Also on Coliru .

这是处理此问题的“正确”方式吗?我应该使用什么语法?是否有多种方法可以达到“默认转发引用”的预期效果?我应该用哪种方式写这个?另请记住,稍后我会在代码中加入大量 SFINAE,因此我更喜欢不包含编写多个重载的内容。

最佳答案

首先,template types cannot be deduced from default arguments .所以我们只能寻找其他方法来实现能够选择性地指定一个参数来匹配转发引用的想法。

这个变通办法本身就是:

template <typename Range, typename Encoding = encoder_t, typename Validation = validator_t>
test ( Range&& range, Encoding&& encoding = encoder, Validation&& validation = validator )
{
}

但是这失败了:转发引用通过将模板类型推导为引用类型来工作,但是您指定了一个对象类型;并且右值引用现在无法绑定(bind)到虚拟对象的左值。

正如您在帖子中所说,您可以通过将默认值设置为临时对象 encoder_t{} 而不是虚拟对象来解决此问题。 This question确认在这种情况下引用确实仍然是转发引用。

另一种解决方法是使用单独的构造函数而不是默认参数:

template <typename Range>
test ( Range&& range )
{
}

template <typename Range, typename Encoding>
test ( Range&& range, Encoding&& encoding )
{
}

template <typename Range, typename Encoding, typename Validation>
test ( Range&& range, Encoding&& encoding, Validation&& validation )
{
}

具体取决于您在构造函数主体中执行的操作,您可以使用构造函数委托(delegate)来实现这一点。

既然你提到了添加 SFINAE 的意图,也许这篇文章会有一些想法:How to allow default construction when using universal reference in constructor

关于c++ - 使用默认参数转发引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27161641/

相关文章:

c# - 基础构造函数的使用

c++ - 静态模板成员的嵌套静态模板成员

c++ - 如何处理 C++ 17 中变体中包含的类型的无意义方法

c++ - 使用 ATL 子类化在 Windows 10 64 位上随机崩溃

c++ - QFileDialog "destroys"文件名

c++模板-类型/值不匹配-使用依赖于派生类的类型实例化基类模板

c++ - 继承自模板抽象类

javascript - 返回构造函数不产生构造函数

c++ - 在 C++ 中从构造函数显式调用析构函数是不好的做法吗?

c++ - 用于 C/C++ 的可移植且简单的 unicode 字符串库?