C++ 混凝土类型的通用参考

C++ 混凝土类型的通用参考,c++,C++,我想要一个函数有一个具体类型的通用引用参数。我希望它是通用引用,这样当我对检查存储在其中的值不感兴趣时,我可以传递一个临时对象 以下是一个例子: bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, size_t &szComparedData) { size_t &i = szComparedData; for (; arg_1[i]; ++i) if (arg_1[i] !

我想要一个函数有一个具体类型的通用引用参数。我希望它是通用引用,这样当我对检查存储在其中的值不感兴趣时,我可以传递一个临时对象

以下是一个例子:

bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, size_t &szComparedData)
{
    size_t &i = szComparedData;

    for (; arg_1[i]; ++i)
        if (arg_1[i] != arg_0[i])
            return false;

    return true;
}
以及可能的函数调用:

bCompareData(Obj.uIdObject.data(), Ref.uIdTargetObject.data(), size_t()) // here we are passing a temporary (rvalue)
/*________________________*/ 
size_t lval;
bCompareData(Obj.uIdObject.data(), Ref.uIdTargetObject.data(), lval) // here we are passing a named variable (lvalue)
在第一个函数调用编译器中使用上述函数声明将产生错误,如果我将“size_t&szComparedData”更改为右值引用“size_t&szComparedData”,则在第二次调用时将失败

现在我需要的是通用引用,但我也希望在我的参数上有一个具体的类型,而不是使用模板


我使用的是VC++U3 2013编译器。

通用参考仅适用于模板和定义的类型推断。您只能使用SFINAE将引用限制为特定类型:

template< typename S >
typename std::enable_if<
    std::is_same<typename std::decay<S>::type,size_t>::value,
bool>::type
bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, S&& szComparedData)
{
    // ...
}

不能有一个通用的参考和不使用模板,因为“通用参考”是一个模板的事情。您想要的是能够传递左值或右值,这可以在没有模板的情况下完成

这里正确的工具是重载。有趣的是,这只需要一个非常简单的重载

bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, size_t &szComparedData)
{
    size_t &i = szComparedData;

    for (; arg_1[i]; ++i)
        if (arg_1[i] != arg_0[i])
            return false;

    return true;
}
bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, size_t &&szComparedData)
{ return bCompareData(arg_0, arg_1, szComparedData);}

这是因为函数参数列表中的
&&
告诉我们该函数参数是由右值构造的,但所有命名值本身都是左值。因为它有名称,所以它是一个左值,您可以简单地将它传递给现有函数。

或者我后来所做的,我认为这不是最好的解决方案:

template <typename T = size_t>

inline bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, T &&arg_2 = size_t())
{
    arg_2 = 0;

    extern bool _bCompareData(const uint8_t *, const uint8_t *, size_t &); //compare data

    return _bCompareData(arg_0, arg_1, arg_2);
}
模板
内联布尔b比较数据(常量uint8\u t*arg\u 0,常量uint8\u t*arg\u 1,t&&arg\u 2=size\u t())
{
arg_2=0;
extern bool\u b比较数据(const uint8\u t*、const uint8\u t*、size\u t&);//比较数据
返回比较数据(参数0、参数1、参数2);
}

C++是一种非常奇怪的语言。我的意思是“右值”和“左值”引用都有相同的大小和属性,那么它们是如何变成不同的类型的。

两者都不匹配
const size\t
variables@PiotrS.:该函数修改输入,因此匹配
常量大小\u t
变量将是一个错误。MSVC是否允许使用第一个变量?(将非常量引用绑定到临时)此处的另一个选项是将其设置为
size\u t*
,然后可以传递
nullptr
(这可能是默认值)如果您对结果不感兴趣,那么您的实现很奇怪。您似乎想要
strcmp
memcmp
或者
std::mismatch
@FrançoisMoisan:从示例中可以看出,参数同时用作输入和输出。@Jako这里有更多想法,函数修改输入,因此,匹配
const size\u t
变量将是一个错误。(此外,我认为您的重载会产生歧义)当函数修改lvalue@MooingDuck是的,但是
A&
A&&
是否明确无误并且适用于所有情况?但也许在这里它是可以的,因为问题确实将它限制为可修改或临时值,不包括常量值。不寻常但可能。@DanielFrey:是的,
A&
A&
是明确的;是
const&
&
造成了歧义,它们都接受临时性。@MooingDuck D'oh,当然。谢谢(答案为+1)它不需要模板,但这是解决问题的一种方法。左值和右值的属性不同。例如,不能为可变引用分配或传递右值
char[12]
std::vector
有时可能具有相同的大小,但人们很难将它们称为相同的类型。
template <typename T = size_t>

inline bool bCompareData(const uint8_t *arg_0, const uint8_t *arg_1, T &&arg_2 = size_t())
{
    arg_2 = 0;

    extern bool _bCompareData(const uint8_t *, const uint8_t *, size_t &); //compare data

    return _bCompareData(arg_0, arg_1, arg_2);
}