C ++ const函数参数。有没有办法只声明单一的功能签名?

时间:2014-07-17 08:18:27

标签: c++ class c++11

我正在处理某个项目,并且在复制功能代码方面存在问题。有没有办法只声明一个函数的单一签名,它将适用于const和非const参数? const和非const函数的实现是相同的。

#include <iostream>

template <class Data>
struct Processor {

    int process(const Data &data)
    {
        return 42;
    }

    int process(Data &data)
    {
        return 42;
    }

};

int main() {

    using data_type = int;

    data_type non_const_data = 1;
    const data_type const_data = 2;

    std::cout << Processor<data_type>().process(non_const_data) << std::endl;
    std::cout << Processor<data_type>().process(const_data) << std::endl;

    return 0;
}

示例http://ideone.com/tv0TsF

感谢您的答复

更新

这个例子怎么样?

#include <iostream>
#include <vector>

template <class Container, class Function>
struct Invoker {

    const Container& invoke(const Container &container, Function function)
    {
        for (auto &value : container) function(value);
    }

    Container& invoke(Container &container, Function function)
    {
        for (auto &value : container) function(value);
    }

};

int main() {

    std::vector<int> container {1, 2, 3};
    auto fn = [](int val) {
        std::cout << val << std::endl;
    };

    Invoker<decltype(container), decltype(fn)>().invoke(container, fn);

    return 0;
}

http://ideone.com/KnyGdT

4 个答案:

答案 0 :(得分:8)

如果两个函数的实现相同,则仅提供const参数函数。在你的情况下,它将同时适用于非const和const对象。

但是,如果要保留这两个函数,可以根据const参数函数实现非const参数函数。它可以帮助您避免重复的代码。

int process(const Data &data)
{
    return 42;
}

int process(Data &data)
{
    return process(static_cast<const Data&>data);
}

答案 1 :(得分:7)

我建议只声明最具限制性的那个,即期望const参数的那个。如果存在向其发送非const指针/引用的问题,您可以在调用方法之前始终使其成为const。

答案 2 :(得分:6)

是:

int process(const Data &data)
{
    return 42;
}

可以使用DataData &Data const &以及任何可转换为Data的内容进行调用。 const引用可以绑定到非const对象或引用。

答案 3 :(得分:1)

它可能不是您正在寻找的,但在const与非const成员函数的情况下会出现类似的情况。有时,例如在访问函数中,您希望有两个版本,一个可用,如果对象是const,另一个可用,当对象是非const时。

struct MyString {
   char & at(int index) {
         if (index < size) {
             return data[index];
         else throw std::range_error("Index out of range");
   }

   char at(int index) const {
         if (index < size) {
             return data[index];
         else throw std::range_error("Index out of range");
   }
};

现在这些功能看起来非常相似,为什么我不能重用一个来实现另一个呢?

答案是你可以,但它需要一些非常小心的转换,首先一般建议是从非const调用const-function。正如您通常可以保证,即使从非const上下文调用const函数也是安全的。对const函数的调用毕竟不会实际改变对象。 (有可变变量的例外情况,或者与我刚才提议的相反。)

解决方案(根据More Effective C++),使用const cast从非const中调用const版本:

   const char & at(int index) const {
         if (index < size) {
             return data[index];
         else throw std::range_error("Index out of range");
   }

   char & at(int index) {
         return const_cast<char &>( static_cast<const MyString>(this)->at(index) );
   }

这有两个功能。首先,将其转换为const指针,这将允许我们调用at()的const版本。然后,一旦我们将const-reference返回给元素,就将它转换为可写引用。