开发者

In C++, in the definition of functions, the argument identifiers are optional. In which scenario this feature could be useful?

int foo(开发者_运维问答int){      
     ...  
}

Any ideas?


When you are not actually using the parameter in the function but do not want to break the public method signature.


One case where you define a function but do not name the parameter is given in Scott Meyers's "Effective C++, 3rd edition", Item 47:

template<typename IterT, typename DistT>        
void doAdvance(IterT& iter, DistT d,            
               std::random_access_iterator_tag) 
{
  iter += d;
}

is used in:

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
  doAdvance( iter, d, 
             typename std::iterator_traits<IterT>::iterator_category() );
}

Essentially, the third parameter in doAdvance is a type unaccompanied by a variable name, i.e. it is an unnamed parameter. Having an unnamed parameter isn't a problem, since that argument is only used during the resolution of which overloaded function to use. I discuss these topics in this related SO question.


This is how the compiler differentiates postfix and prefix increment operators -- X operator++() is prefix, X operator++(int) is postfix.

Because the int is never actually used in the postfix operator, there's no reason to give it a name. This is generally why you get unnamed parameters, to overload a function or operator to mean two slightly different things. This is a common trick in template metaprogramming as used in Loki and Boost.


In some cases, compilers will warn of unused parameters, unless you leave off the identifier name as you show. It's also potentially useful to show that a parameter is unused. Other than that, I have no idea. You certainly can't leave the identifier off if you use the parameter.


Extra parameters can be used by SFINAE, for overload resolution or dispatch depending on type properties.

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <boost/call_traits.hpp>
#include <iostream>
#include <string>

// use SFINAE enable this function for numerical types only
template <class T>
double foo(T t, typename
                boost::enable_if<boost::is_floating_point<T> >::
                type* dummy = 0) {
    double x = static_cast<double>(t);
    return x;
}

// use extra parameter for overload resolution
struct PlanA {};
struct PlanB {};

void bar(const PlanA&) {
    std::cout << "using plan A...\n";
}

void bar(const PlanB&) {
    std::cout << "using plan B...\n";
}

// use type traits to choose which function to call
template <typename T>
double fooBar(T t) {
    return dispatch(t, boost::is_convertible<T, double>());
}

double dispatch(double t, const boost::true_type&) {
    std::cout << "convertible to double\n";
    return t+0.1;
}

template <typename T>
double dispatch(const T&, const boost::false_type&) {
    std::cout << "not convertible to double\n";
    return 0.0;
}


int main () {

    foo(1.0);
    // foo(1); won't compile

    bar(PlanA());
    bar(PlanB());

    std::string name = "John Dow";

    fooBar(1.0);
    fooBar(name);
}


You do it when you're implementing a function of some signature, don't actually need the parameter (quite common in hierarchies behind an abstract), and need to compile without warnings. Since all projects should be set to break when there's a warning, and this comes up a LOT in OOP/GP, it's a very, very common thing to do. It's so common in fact that many libraries have a mylibUNUSED() macro for better legibility.


Note that from the fact that the compiler doesn't care about the actual parameter name comes the fact that you can use different parameter names for a function( template)'s declaration than for it's definition.

This is useful when you have a library that you ship as headers and as lib file and everyone using your API will not want to have to re-compile everything just because, inside of the library, you change the names of some parameter(s). (You probably have to have been in a multi-MLoC C++ project to appreciate that.)


I think you mean in the declaration of functions. Actually, you can also omit the indentifier name in the definition of functions, but this will cause a compilation error if the parameter is used, which is likely to happen.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜