Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a function template the least priority during ADL?

I have a problem where I'd like to provide a generic version of a function foo which may only be applied when there is absolutely no other match for an invocation. How can I modify the following code such that last_resort::foo is a worse match for derived::type than base::foo? I'd like to find a solution which does not involve modifying the definition of bar and which would preserve the type of the argument of last_resort::foo.

#include <iostream>

namespace last_resort
{

template<typename T> void foo(T)
{
  std::cout << "last_resort::foo" << std::endl;
}

}

template<typename T> void bar(T)
{
  using last_resort::foo;
  foo(T());
}

namespace unrelated
{

struct type {};

}

namespace base
{

struct type {};

void foo(type)
{
  std::cout << "base::foo" << std::endl;
}

}

namespace derived
{

struct type : base::type {};

}

int main()
{
  bar(unrelated::type()); // calls last_resort::foo
  bar(base::type());      // calls base::foo
  bar(derived::type());   // should call base::foo, but calls last_resort::foo instead

  return 0;
}
like image 689
Jared Hoberock Avatar asked Sep 30 '11 18:09

Jared Hoberock


People also ask

How do you define a function template?

Defining a Function TemplateA function template starts with the keyword template followed by template parameter(s) inside <> which is followed by the function definition. In the above code, T is a template argument that accepts different data types ( int , float , etc.), and typename is a keyword.

Which one is suitable syntax for function template?

Which one is suitable syntax for function template? Explanation: Both class and typename keywords can be used alternatively for specifying a generic type in a template.

When the actual code for a template function is generated?

A code for template function is generated when the function is instantiated. The functions are often instantiated when they are first time called (in the code), but there are other ways to instantiate a function - do a so-called 'explicit instantiation'.

How does ADL work C++?

In the C++ programming language, argument-dependent lookup (ADL), or argument-dependent name lookup, applies to the lookup of an unqualified function name depending on the types of the arguments given to the function call.


1 Answers

This would be about as bad as it gets:

struct badParam { template <typename T> badParam(T t) { } };
namespace last_resort {
  void foo(badParam, int dummy = 0, ...) {
    std::cout << "last_resort::foo" << std::endl;
  }
}

You've got a user-defined conversion, a defaulted parameter and an unused ellipsis.

[edit]

Slight variant, to save T I moved the user-defined conversion to the dummy parameter:

struct badParam { 
    badParam() { }
    operator int() { return 42; }
};
namespace last_resort {
  template <typename T> void foo(T t, int dummy = badParam(), ...) {
    std::cout << "last_resort::foo" << std::endl;
  }
}
like image 80
MSalters Avatar answered Sep 28 '22 06:09

MSalters