I know I cannot use a namespace as a template parameter. However, I'm trying to achieve behavior similar to this:
template <typename T>
void foo(T::X* x)
{
T::bar(x);
}
Except T is a namespace rather than a struct or a class. What is the best way to achieve the most similar result to what I am expecting?
Except T is a namespace rather than a struct or a class. What is the best way to achieve the most similar result to what I am expecting?
Don't mention T at all.
template <typename X>
void foo(X* x)
{
bar(x);
}
ADL will always pick up on overloads from the namespace where X is defined. Let the mechanism do its work.
Now, if you are asking how to make the compiler favor functions found by ADL, it's all about manipulating overload resolution. We can do that by limiting what is picked up by regular unqualified name lookup:
namespace foo_detail {
void bar(...);
template<typename X>
void foo_impl(X* x) {
bar(x);
}
}
template <typename X>
void foo(X* x)
{
foo_detail::foo_impl(x);
}
When the call in foo_detail::foo_impl is trying to resolve bar, the first phase in two-phase lookup will pickup the C variable argument function. Now lookup stops, no further enclosing namespaces will be looked in. Which means that only ADL can offer more candidates. And due to how overload resolution works, a C-style variable argument function like we added will be a worse match than anything ADL will find.
Here's a live example for all of this at work.
Namespace can't be a template parameter.
The only possible template parameters are:
types
and values which are: Template parameters and template arguments - cppreference.com
std::nullptr_t (since C++11);
an integral type;
a pointer type (to object or to function);
a pointer to member type (to member object or to member function);
an enumeration type.
So if you want change bar version depending on namespace it can't be done like you proposed.
It can be achieved if bar is enclosed in class as a static function. In such case you can use your template, then that class becomes template parameter.
So your code can look lie this:
class Variant1 {
public:
typedef int* argType;
static void bar(argType i) {
std::cout << (*i + 1);
}
};
class Variant2 {
public:
typedef size_t* argType;
static void bar(argType i) {
std::cout << (*i - 1);
}
};
template <typename T>
void foo(typename T::argType x)
{
T::bar(x);
}
//usage
size_t a = 1;
int x = 1;
foo<Variant1>(&a);
foo<Variant2>(&b);
Related
I've been using C# so long, I have a couple of questions about function templates in C++.
template <typename T>
T max(T x, T y)
{
return (x > y) ? x : y;
}
Why do some examples use typename and other examples use class in the template parameter declaration? What is the difference?
Is there any way to restrict T to a particular type, or to a type that derives from a particular type?
Is there any way for a class to have two methods with the same name, except one is templated and the other is not?
UPDATE:
I appreciate all the answers, but several of them contain examples that I won't compile when I try to apply them to my code.
To clarify question 3, I have the following method:
template<typename T>
std::unique_ptr<T> ExecuteSqlQuery(LPCTSTR pszSqlQuery, UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE);
I would like to declare a variation of this that uses CRecordset as T, so that either of the following statements would be valid:
auto result = db.ExecuteSqlQuery<CCustomerRecordset>(L"SELECT ...");
auto result = db.ExecuteSqlQuery(L"SELECT ...");
Why do some examples use typename and other examples use class in the template parameter declaration? What is the difference?
There is no difference between the two in the template parameter declaration, however they both have additional separate meanings in other contexts. E.g. typename is used to mark dependent names as type names and class is used to introduce a class declaration.
Is there any way to restrict T to a particular type, or a type that derives from a particular type?
Yes, one way is to rely on SFINAE to discard instantiations of types satisfying some condition, often facilitated by std::enable_if, e.g. (using C++14):
template<typename T, typename = std::enable_if_t<std::is_base_of_v<SomeBaseClass, T>>
T max(T x, T y)
{
return (x > y) ? x : y;
}
In the upcoming C++20, there will be support for Concepts, which allow one to write
template<std::DerivedFrom<SomeBaseClass> T>
T max(T x, T y)
{
return (x > y) ? x : y;
}
Is there any way for a class to have two methods with the same name, except one is templated and the other is not?
Yes, this is possible. In overload resolution, if both candidates would be equally well matching, the non-templated one will be preferred.
In this particular context both class and typename mean exaclty the same, there is no difference. class is just a bit shorter :-).
Until C++20 we could try and restrict template arguments using sophisticated template metaprogramming in conjunction with SFINAE technique. Basically, it makes template instantiation fail if the argument does not satisfy some condition. While it's very powerfull approach, it has its drawbacks: increased compile times and very long and unclear error messages.
In C++20 we have a new language feature named concepts, which is aimed to do exactly the same in a simple and straightforward way.
Yes, a function template can be overloaded with a regular function. If the both match, the regular function will be chosen. Note however that in general template overload resolution is quite complicated topic.
Why do some examples use typename and other examples use class in the template parameter declaration? What is the difference?
Historically,
Only typename was allowed for simple template, and class should be used for template template parameter:
template <template <typename> class C> void foo();
with usage such as
foo<std::unique_ptr>();
There are now (C++17) interchangeable in those contexts.
Is there any way to restrict T to a particular type, or to a type that derives from a particular type?
You might do that with SFINAE (which has several syntaxes), and in C++20 with Concepts.
template <typename T>
std::enable_if_t<some_trait<T>::value> foo();
Is there any way for a class to have two methods with the same name, except one is templated and the other is not?
Yes you might have several overloads that way
template <template <class> typename C> void foo();
template <int> void foo();
void foo();
or more simply
template <typename T> void foo(T); // #1
void foo(int); // #2
// Note that foo<int> (#1 with T = int) is different than foo (#2)
Old school C++ used 'class', but we now use 'typename'. You can still use class, but typename is recommended.
Yes, you can restrict types via specialisation..
template<typename T> T foo(T x); //< no implementation in the generic case
template<> T foo<float>(T x) { return x; } //< float is allowed
template<> T foo<double>(T x) { return x; } //< double is allowed
And you can handle derived types as well (and there are a few ways to do this)
#include <string>
#include <iostream>
struct Cow {};
template<typename T>
struct Moo
{
// default to false
template<bool valid = std::is_base_of<Cow, T>::value>
static void moo()
{
std::cout << "No moo for you!" << std::endl;
}
// moo if T is a cow
template<>
static void moo<true>()
{
std::cout << "Mooooo!" << std::endl;
}
};
struct AberdeenAngus : public Cow {};
struct Sheep {};
int main()
{
Moo<AberdeenAngus>::moo();
Moo<Sheep>::moo();
return 0;
}
Yes.
class Foo
{
public:
template<typename T>
T thing(T a) { return a; } //< template
float thing(float a) { return a * 5.0f; } //< function overload
};
I was messing around with some code when this weird behavior occurred :
In the first test, base templated function, user and templated specialization lie within the same namespace and it behaves as I expect :
namespace Test1
{
template <typename V, typename T>
int doFoo(V& a_visitor, T& a_value)
{
return 0;
}
struct Foo
{
template <typename T>
int process(T const& a_value)
{
return doFoo(*this, a_value);
}
};
template <typename T>
int doFoo(Foo& a_vis, T const& a_ptr)
{
return 1;
}
}
int main()
{
int const k{ 42 };
return Test1::Foo{}.process(k); // returns 1
}
but when I move base templated function and its specialization in another namespace, the base one is selected :
namespace Test2
{
namespace b
{
template <typename V, typename T>
int doBar(V& a_visitor, T& a_value)
{
return 0;
}
}
struct Bar
{
template <typename T>
int process(T const& a_value)
{
return b::doBar(*this, a_value);
}
};
namespace b
{
template <typename T>
int doBar(Bar& a_vis, T const& a_ptr)
{
return 1;
}
}
}
int main()
{
int const k{ 17 };
return Test2::Bar{}.process(k); // returns 0
}
EDIT I can do even weirder : in example 1 if I replace call to doFoo with Test1::doFoo I get the wrong behavior again !
Could anyone explain me what is going on here ? How can I do if I really need struct Bar not to be within namespace b ?
To begin with, those aren't specializations, those are overloads. Completely different function templates that aren't related to each other.
The behavior you see is consistent with argument-dependent lookup. When encountering an unqualified function call, the compiler builds an overload set by examining the namespaces associated with each argument to the function call.
Normally this won't find declarations the come "after", but templates are special. In templates lookup for a dependent name, such as a function call that depends on a template parameter (the type of a_value), is performed after the template is instantiated, and not at the point of definition. That occurs in main, after the namespace is complete and all overloads are available, and so ADL finds the second overload.
This is also why when you qualify the call by Test1 you no longer find the second overload. That negates ADL, and only allows for overloads that appear prior to the point of the call. The easiest way to resolve it would probably be to delay the definition of process until all overloads are available, as other answers indicate.
I am writing a library and there is a function that performs an (unqualified) call to free function foo using an arbitrary type as argument:
namespace lib {
template <typename T>
auto libfunc(T && t)
{
return foo(std::forward<T>(t));
}
} // namespace lib
A user of the library can write an overload of foo for his own types:
namespace app {
class Foo { };
template <typename> class Bar { };
int foo(Foo const &) { return 99; }
template <typename T>
char foo(Bar<T> const &) { return 'x'; }
} // namespace app
The correct funtion foo is found by ADL so code like this works:
app::Foo foo;
app::Bar<void**> bar;
auto x = lib::libfunc(foo);
auto y = lib::libfunc(bar);
However, if I want to write a version of foo that works for types from the std-namespace, no matching function foo is found unless I place foo in the std-namespace which is not allowed:
#ifdef EVIL
namespace std {
#endif
template <typename T>
double foo(std::vector<T> const & ) { return 1.23; }
#ifdef EVIL
} // namespace std
#endif
std::vector<int> vec;
lib::libfunc(vec); // Only works if EVIL is defined
Is it possible to change the code so that a user can enable the functionality foo for a type without invading its namespace? I thought about partial template specializations of a class template in the lib-namespace but is there any other possibility?
I've found two solutions to this problem. Both have their downsides.
Declare All Std Overloads
Let overloads for standard types be found by normal lookup. This basically means declaring all of them before using the extension function. Remember: when you perform an unqualified call in a function template, normal lookup happens at the point of definition, while ADL happens at the point of instantiation. This means that normal lookup only finds overloads visible from where the template is written, whereas ADL finds stuff defined later on.
The upside of this approach is that nothing changes for the user when writing his own functions.
The downside is that you have to include the header of every standard type you want to provide an overload for, and provide that overload, in the header that just wants to define the extension point. This can mean a very heavy dependency.
Add Another Argument
The other option is to pass a second argument to the function. Here's how this works:
namespace your_stuff {
namespace adl {
struct tag {}
void extension_point() = delete; // this is just a dummy
}
template <typename T>
void use_extension_point(const T& t) {
using adl::extension_point;
extension_point(t, adl::tag{}); // this is the ADL call
}
template <typename T>
void needs_extension_point(const T& t) {
your_stuff::use_extension_point(t); // suppress ADL
}
}
Now you can, at basically any point in the program, provide overloads for std (or even global or built-in) types like this:
namespace your_stuff { namespace adl {
void extension_point(const std::string& s, tag) {
// do stuff here
}
void extension_point(int i, tag) {
// do stuff here
}
}}
The user can, for his own types, write overloads like this:
namespace user_stuff {
void extension_point(const user_type& u, your_stuff::adl::tag) {
// do stuff here
}
}
Upside: Works.
Downside: the user must add the your_stuff::adl::tag argument to his overloads. This will be probably seen as annoying boilerplate by many, and more importantly, can lead to the big puzzling "why doesn't it find my overload" problem when the user forgets to add the argument. On the other hand, the argument also clearly identifies the overloads as fulfilling a contract (being an extension point), which could be important when the next programmer comes along and renames the function to extensionPoint (to conform with naming conventions) and then freaks out when things don't compile anymore.
So, I know that there is a difference between these two tidbits of code:
template <typename T>
T inc(const T& t)
{
return t + 1;
}
template <>
int inc(const int& t)
{
return t + 1;
}
and
template <typename T>
T inc(const T& t)
{
return t + 1;
}
int inc(const int& t)
{
return t + 1;
}
I am confused as to what the functional differences between these two are. Can someone show some situations where these snippits act differently from each other?
I can only think of a few differences - here are some examples that don't necessarily cause harm (i think). I'm omitting definitions to keep it terse
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
template <> int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses explicit specialization
// --- against ---
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses template
That is because specializations are not found by name lookup, but by argument matching, so a using declaration will automatically consider a later introduced specialization.
Then, you of course cannot partially specialize function templates. Overloading however accomplishes something very similar by partial ordering (using different types now, to make my point)
template <typename T> void f(T t); // called for non-pointers
template <typename T> void f(T *t); // called for pointers.
int a;
void e() {
f(a); // calls the non-pointer version
f(&a); // calls the pointer version
}
That wouldn't be possible with function template explicit specialization. Another example is when references are involved, which causes template argument deduction to look for an exact match of the types involved (modulo base/derived class relationships and constness):
template<typename T> void f(T const &);
template<> void f(int * const &);
template<typename T> void g(T const &);
void g(int * const &);
int a[5];
void e() {
// calls the primary template, not the explicit specialization
// because `T` is `int[5]`, not `int *`
f(a);
// calls the function, not the template, because the function is an
// exact match too (pointer conversion isn't costly enough), and it's
// preferred.
g(a);
}
I recommend you to always use overloading, because it's richer (allows something like partial specialization would allow), and in addition you can place function in whatever namespace you want (although then it's not strictly overloading anymore). For example, instead of having to specialize std::swap in the std:: namespace, you can place your swap overload in your own namespace and make it callable by ADL.
Whatever you do, never mix specialization and overloading, it will be a hell of a mess like this article points out. The Standard has a lovely paragraph about it
The placement of explicit specialization declarations for function templates, class templates, member functions of class templates, static data members of class templates, member classes of class templates, member class templates of class templates, member function templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, member class templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below. When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
Template specialization is more generic than just overloading. You can specialize things like classes rather than just simple functions. Overloading only applies to functions.
UPDATE: To clarify more per AraK's comment, you are really comparing apples and oranges here. Function overloading is used to introduce the ability to have different functions share a single name, if they have different signatures. Template specialization is used to define a specific code snippet for a specific type parameter. You can't have a template specialization if you don't have a template. If you remove the first piece of code that declares the generic template, you'll receive a compile time error if you try to use template specialization.
So, the goal of template specialization is pretty different from a function overload. They just happen to behave similarly in your example while they are fundamentally different.
If you provide an overload, you are declaring an independent method that happens to have the same name. You are not preventing the template to be used with the specific type parameter. To demonstrate this fact, try:
template <typename T>
T inc(const T& t)
{
return t + 1;
}
int inc(const int& t)
{
return t + 42;
}
#include <iostream>
int main() {
int x = 0;
x = inc<int>(x);
std::cout << "Template: " << x << std::endl; // prints 1.
x = 0;
x = inc(x);
std::cout << "Overload: " << x << std::endl; // prints 42.
}
As you can see, in this example, there are two distinct inc functions for int values: inc(const int&) and inc<int>(const int&). You couldn't expand the generic template using int if you had used template specialization.
One such example:
#include <cstdio>
template <class T>
void foo(T )
{
puts("T");
}
//template <>
void foo(int*)
{
puts("int*");
}
template <class T>
void foo(T*)
{
puts("T*");
}
int main()
{
int* a;
foo(a);
}
It is actually suggested that you use non-template overloads for functions and leave specialization for classes. It is discussed at greater length in Why Not Specialize Function Templates?
AFAIK there is no functional difference. All I can add is that if you have both a template function specialisation and an ordinary function defined then there is no overload ambiguity as the ordinary function is favoured.
Just to elaborate on the first point mentioned by litb in his answer. Specializations are only checked once overload resolution has actually selected a primary template. The result can lead to some surprises where a function is overloaded and has explicit specializations:
template <typename T> void foo (T); // Primary #1
template <> void foo<int*> (int*); // Specialization of #1
template <typename T> void foo (T*); // Primary #2
void bar (int * i)
{
foo(i);
}
When choosing which function to call, the following steps take place:
Name lookup finds both primary templates.
Each template is specialized and overload resolution attempts to select a best function based on conversions between the arguments and parameters.
In thise case, there is no difference in the quality of the conversions.
Partial ordering rules are then used to select the most specialized template. In this case that is the second parimary "foo(T*)".
Only after these steps, when the best function has been selected will explicit specializations of the selected function be considered. (In this case primary #2 has none so none are considered).
The only way to call the above explicit specialization here, is to actually use explicit template arguments in the call:
void bar (int * i)
{
foo<int*> (i); // expliit template argument forces use of primary #1
}
A good rule of thumb is to try to avoid having overloads that are also explicily specialized, as the resulting rules are pretty complex.
I want to do something like
template <typename T>
void foo(const T& t) {
IF bar(t) would compile
bar(t);
ELSE
baz(t);
}
I thought that something using enable_if would do the job here, splitting up foo into two pieces, but I can't seem to work out the details. What's the simplest way of achieving this?
There are two lookups that are done for the name bar. One is the unqualified lookup at the definition context of foo. The other is argument dependent lookup at each instantiation context (but the result of the lookup at each instantiation context is not allowed to change behavior between two different instantiation contexts).
To get the desired behavior, you could go and define a fallback function in a fallback namespace that returns some unique type
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag bar(...);
}
The bar function will be called if nothing else matches because the ellipsis has worst conversion cost. Now, include that candidates into your function by a using directive of fallback, so that fallback::bar is included as candidate into the call to bar.
Now, to see whether a call to bar resolves to your function, you will call it, and check whether the return type is flag. The return type of an otherwise chosen function could be void, so you have to do some comma operator tricks to get around that.
namespace fallback {
int operator,(flag, flag);
// map everything else to void
template<typename T>
void operator,(flag, T const&);
// sizeof 1
char operator,(int, flag);
}
If our function was selected then the comma operator invocation will return a reference to int. If not or if the selected function returned void, then the invocation returns void in turn. Then the next invocation with flag as second argument will return a type that has sizeof 1 if our fallback was selected, and a sizeof greater 1 (the built-in comma operator will be used because void is in the mix) if something else was selected.
We compare the sizeof and delegate to a struct.
template<bool>
struct foo_impl;
/* bar available */
template<>
struct foo_impl<true> {
template<typename T>
static void foo(T const &t) {
bar(t);
}
};
/* bar not available */
template<>
struct foo_impl<false> {
template<typename T>
static void foo(T const&) {
std::cout << "not available, calling baz...";
}
};
template <typename T>
void foo(const T& t) {
using namespace fallback;
foo_impl<sizeof (fallback::flag(), bar(t), fallback::flag()) != 1>
::foo(t);
}
This solution is ambiguous if the existing function has an ellipsis too. But that seems to be rather unlikely. Test using the fallback:
struct C { };
int main() {
// => "not available, calling baz..."
foo(C());
}
And if a candidate is found using argument dependent lookup
struct C { };
void bar(C) {
std::cout << "called!";
}
int main() {
// => "called!"
foo(C());
}
To test unqualified lookup at definition context, let's define the following function above foo_impl and foo (put the foo_impl template above foo, so they have both the same definition context)
void bar(double d) {
std::cout << "bar(double) called!";
}
// ... foo template ...
int main() {
// => "bar(double) called!"
foo(12);
}
litb has given you a very good answer. However, I wonder whether, given more context, we couldn't come up with something that's less generic, but also less, um, elaborate?
For example, what types can be T? Anything? A few types? A very restricted set which you have control over? Some classes you design in conjunction with the function foo? Given the latter, you could simple put something like
typedef boolean<true> has_bar_func;
into the types and then switch to different foo overloads based on that:
template <typename T>
void foo_impl(const T& t, boolean<true> /*has_bar_func*/);
template <typename T>
void foo_impl(const T& t, boolean<false> /*has_bar_func*/);
template <typename T>
void foo(const T& t) {
foo_impl( t, typename T::has_bar_func() );
}
Also, can the bar/baz function have just about any signature, is there a somewhat restricted set, or is there just one valid signature? If the latter, litb's (excellent) fallback idea, in conjunction with a meta-function employing sizeof might be a bit simpler. But this I haven't explored, so it's just a thought.
I think litb's solution works, but is overly complex. The reason is that he's introducing a function fallback::bar(...) which acts as a "function of last resort", and then goes to great lengths NOT to call it. Why? It seems we have a perfect behavior for it:
namespace fallback {
template<typename T>
inline void bar(T const& t, ...)
{
baz(t);
}
}
template<typename T>
void foo(T const& t)
{
using namespace fallback;
bar(t);
}
But as I indicated in a comment to litb's original post, there are many reasons why bar(t) could fail to compile, and I'm not certain this solution handles the same cases. It certainly will fail on a private bar::bar(T t)
If you're willing to limit yourself to Visual C++, you can use the __if_exists and __if_not_exists statements.
Handy in a pinch, but platform specific.
EDIT: I spoke too soon! litb's answer shows how this can actually be done (at the possible cost of your sanity... :-P)
Unfortunately I think the general case of checking "would this compile" is out of reach of function template argument deduction + SFINAE, which is the usual trick for this stuff. I think the best you can do is to create a "backup" function template:
template <typename T>
void bar(T t) { // "Backup" bar() template
baz(t);
}
And then change foo() to simply:
template <typename T>
void foo(const T& t) {
bar(t);
}
This will work for most cases. Because the bar() template's parameter type is T, it will be deemed "less specialised" when compared with any other function or function template named bar() and will therefore cede priority to that pre-existing function or function template during overload resolution. Except that:
If the pre-existing bar() is itself a function template taking a template parameter of type T, an ambiguity will arise because neither template is more specialised than the other, and the compiler will complain.
Implicit conversions also won't work, and will lead to hard-to-diagnose problems: Suppose there is a pre-existing bar(long) but foo(123) is called. In this case, the compiler will quietly choose to instantiate the "backup" bar() template with T = int instead of performing the int->long promotion, even though the latter would have compiled and worked fine!
In short: there's no easy, complete solution, and I'm pretty sure there's not even a tricky-as-hell, complete solution. :(
//default
//////////////////////////////////////////
template <class T>
void foo(const T& t){
baz(t);
}
//specializations
//////////////////////////////////////////
template <>
void foo(const specialization_1& t){
bar(t);
}
....
template <>
void foo(const specialization_n& t){
bar(t);
}
Are you not able to use full specialisation here (or overloading) on foo. By say having the function template call bar but for certain types fully specialise it to call baz?