Adrian
Adrian

Reputation: 10911

Range based for loop doesn't work with pointer even when begin()/end() defined for it?

According to range based for loop documentation here:

begin_expr and end_expr are defined as follows:

  • If range_expression is an expression of array type, then begin_expr is __range and end_expr is (__range + __bound), where __bound is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed)
  • If range_expression is an expression of a class type C that has a member named begin and/or a member named end (regardless of the type or accessibility of such member), then begin_expr is __range.begin) and end_expr is __range.end();
  • Otherwise, begin_expr is begin(__range) and end_expr is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed).

However, if I define begin() and end() for a pointer type, it fails to work.

Example

#include <iostream>

using LPCSTR = char const*;

LPCSTR begin(LPCSTR str)
{
    return str;
}

LPCSTR end(LPCSTR str)
{
    return str + strlen(str);
}

int main()
{
    LPCSTR text = "Hello, world!\n";
    for (auto c : text)
    {
        std::cout << c;
    }
}

Error(s):

source_file.cpp:18:17: error: invalid range expression of type 'const char *'; no viable 'begin' function available
    for (auto c : text)
                ^ ~~~~
1 error generated.

Demo

I don't see any reference that pointers are excluded from the ADL, so what reason would there be as to why this isn't working?

Upvotes: 1

Views: 1394

Answers (2)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

[basic.lookup.argdep]/2 For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered...

(2.1) — If T is a fundamental type, its associated sets of namespaces and classes are both empty...

(2.4) — If T is a pointer to U or an array of U, its associated namespaces and classes are those associated with U...

From these, a set of namespaces asscociated with char const* is empty, so there's nothing for ADL to look at.

Upvotes: 2

mpark
mpark

Reputation: 7904

The issue is this part:

non-ADL lookup is not performed

begin and end in this context would be found by non-ADL lookup, rather than ADL since pointers aren't "defined in the global namespace".

Upvotes: 0

Related Questions