Template functions in namespace cause errors - c++

Assume the following code:
#include <iostream>
template<typename T>
struct Link
{
Link(T&& val) : val(std::forward<T>(val)) {}
T val;
};
template<typename T>
std::ostream& operator<<(std::ostream& out, const Link<T>& link)
{
out << "Link(" << link.val << ")";
return out;
}
template<typename T>
auto MakeLink(T&& val) -> Link<T>
{
return {std::forward<T>(val)};
}
namespace Utils {
template<typename Any>
constexpr auto RemoveLinks(const Any& any) -> const Any&
{
return any;
}
template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val))
{
return RemoveLinks(link.val);
}
} /* Utils */
int main()
{
int k = 10;
auto link = MakeLink(MakeLink(k));
std::cout << link << std::endl;
std::cout << Utils::RemoveLinks(link) << std::endl;
}
For some reason I can't understand, it generates the following compilation errors with g++-4.8:
/home/allan/Codes/expr.cpp: In instantiation of ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const int&]’:
/home/allan/Codes/expr.cpp:88:32: required from ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = Link<int&>; decltype (Utils::RemoveLinks(link.val)) = const int&]’
/home/allan/Codes/expr.cpp:100:41: required from here
/home/allan/Codes/expr.cpp:88:32: error: invalid initialization of reference of type ‘const Link<int&>&’ from expression of type ‘const int’
return RemoveLinks(link.val);
^
/home/allan/Codes/expr.cpp:89:1: error: body of constexpr function ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const Link<int&>&]’ not a return-statement
}
^
/home/allan/Codes/expr.cpp: In function ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const int&]’:
/home/allan/Codes/expr.cpp:89:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
while clang 3.3 gives:
test.cc:34:12: error: reference to type 'const Link<int &>' could not bind to an lvalue of type 'const int'
return RemoveLinks(link.val);
^~~~~~~~~~~~~~~~~~~~~
test.cc:46:25: note: in instantiation of function template specialization 'Utils::RemoveLinks<Link<int &> >' requested here
std::cout << Utils::RemoveLinks(link) << std::endl;
If, however, the namespace Utils is removed, then it compiles without errors (both gcc and clang), and execution outputs:
Link(Link(10))
10
Why defining those template functions (RemoveLinks) in a namespace causes such errors?

This problem is a result of an issue with the point of declaration (1) combined with dependent name lookup (2).
(1) In the declaration
template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val))
the name RemoveLinks, or more precisely, this overload of RemoveLinks, is only visible after the complete declarator according to [basic.scope.pdecl]/1. The trailing-return-type is part of the declarator as per [dcl.decl]/4. Also see this answer.
(2) In the expression RemoveLinks(link.val), the name RemoveLinks is dependent as per [temp.dep]/1, as link.val is dependent.
If we now look up how dependent names are resolved, we find [temp.dep.res]:
In resolving dependent names, names from the following sources are considered:
Declarations that are visible at the point of definition of the template.
Declarations from namespaces associated with the types of the function arguments both from the instantiation context and from the definition context.
The first bullet doesn't find the second overload of RemoveLinks because of the point of declaration (1). The second one doesn't find the overload because the namespace Util is not associated with any argument. This is why putting everything in the global namespace or in the namespace Util works as expected (Live example).
For the same reason, using a qualified-id in the trailing-return-type (like -> decltype(Util::RemoveLinks(link.val)) doesn't help here.

I tried compiling the sample code above with GCC 4.8.1, with clang and also Intel icpc and got the same error messages as you.
I am able to get it to successfully compile without trouble if I revise the signature of the template specialization from:
template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val))
and make the return type as const. This might cause a compiler warning since the const there is meaningless, but that can be ignored. I tested it and it works fine for me with gcc, but not icpc or clang:
template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val)) const
I found the error message (with the original code) from Intel icpc to be the most informative:
code.cc(48): error: template instantiation resulted in unexpected function type of "auto (const Link<Link<int &>> &)->const int &" (the meaning of a name may have changed since the template declaration -- the type of the template is "auto (const Link<T> &)->decltype((<expression>))")
std::cout << Utils::RemoveLinks(link) << std::endl;
^
detected during instantiation of "Utils::RemoveLinks" based on template argument <Link<int &>> at line 48
Unfortunately, the above answer is more of a workaround for gcc rather than an answer to your question. I'll update this if I have anything more / better to add.
EDIT
It appears that decltype(RemoveLinks(link.val)) is actually following the recursion so that it returns int& rather than Link.
EDIT #2
There have been reported bugs in LLVM about crashes caused by decltype recursion problems. It seems that this is definitely a bug of sorts, but one that seems to be present in multiple implementations of C++.
The problem can be fixed quite easily if you create a an alias for type T in the link struct and have decltype refer to the alias rather than to the return type. This will eliminate the recursion. As follows:
template<typename T>
struct Link
{
Link(T&& val) : val(std::forward<T>(val)) {}
using value_type = T;
T val;
};
And then the RemoveLinks signature is changed accordingly to refer to this alias:
template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(links.value_type)
This code successfully builds on all 3 compilers.
I will file some bug reports with the compilers to see if there's anything they can do about it.
Hope this helps.

Related

"Cannot form reference to void" error even with `requires(!std::is_void_v<T>)`

I'm writing a pointer class and overloading the dereference operator operator*, which returns a reference to the pointed-to object. When the pointed-to type is not void this is fine, but we cannot create a reference to void, so I'm trying to disable the operator* using a requires clause when the pointed-to type is void.
However, I'm still getting compiler errors from GCC, Clang, and MSVC for the void case even though it does not satisfy the requires clause.
Here is a minimal example and compiler explorer link (https://godbolt.org/z/xbo5v3d1E).
#include <iostream>
#include <type_traits>
template <class T>
struct MyPtr {
T* p;
T& operator*() requires(!std::is_void_v<T>)
{
return *p;
}
};
int main() {
int x = 42;
MyPtr<int> i_ptr{&x};
*i_ptr = 41;
MyPtr<void> v_ptr{&x};
std::cout << *static_cast<int*>(v_ptr.p) << '\n';
std::cout << x << '\n';
return 0;
}
And here is the error (in Clang):
<source>:7:6: error: cannot form a reference to 'void'
T& operator*()
^
<source>:20:17: note: in instantiation of template class 'MyPtr<void>' requested here
MyPtr<void> v_ptr{&x};
^
1 error generated.
ASM generation compiler returned: 1
<source>:7:6: error: cannot form a reference to 'void'
T& operator*()
^
<source>:20:17: note: in instantiation of template class 'MyPtr<void>' requested here
MyPtr<void> v_ptr{&x};
^
1 error generated.
Execution build compiler returned: 1
However, if I change the return type of operator* from T& to auto&, then it works in all 3 compilers. If I use trailing return type auto ... -> T& I also get errors in all 3 compilers.
Is this a triple compiler bug, user error, or is this intended behavior?
The requires clause doesn't matter because T is a parameter of the class template. Once T is known, the class can be instantiated, but if T is void, that instantiation fails because of the member function signature.
You can either put that requires on the entire class, or make the member function a template like this:
template<typename U = T>
U& operator*() requires(!std::is_void_v<U> && std::is_same_v<T, U>)
{
return *p;
}
Demo
Making the return type auto& is almost the same thing: the return type is deduced by replacing auto with an imaginary type template parameter U and then performing template argument deduction. Note that the version above with requires makes the compilation error clear if you try to use this function with U=void: GCC says template argument deduction/substitution failed: constraints not satisfied.
I don't think there is a way to reproduce exactly what an auto& return type does by making the function a template. Something like this might come close:
template<typename U = T>
std::enable_if_t<!std::is_void_v<T>, U>& operator*()
{
return *p;
}
Compare what you're trying with the equivalent using std::enable_if (without concepts):
template<std::enable_if_t<!std::is_void_v<T>, bool> = true>
T& operator*()
{
return *p;
}
This will give you an error like no type named 'type' in 'struct std::enable_if<false, bool>', because SFINAE wouldn't work in this situation where T is not a parameter of the function template.
Technically, you can also change the return type depending on whether T is void, but this is probably a bad idea:
using R = std::conditional_t<std::is_void_v<T>, int, T>;
R& operator*()
{
// calling this with T=void will fail to compile
// 'void*' is not a pointer-to-object type
return *p;
}
In addition to the Nelfeal's answer, let me give an alternative solution. The problem is not in the dependence of requires condition on T, but is in the return type T&. Let's use a helper type trait:
std::add_lvalue_reference_t<T> operator*()
requires(!std::is_void_v<T>)
{
...
}
It works because std::add_lvalue_reference_t<void> = void, which makes operator*() signature valid for T = void.

Convert constexpr struct to a runtime one

I'm trying to use a template class (here Foo), with a basic type like:
hana::tuple<hana::pair<hana::type<int>, Runtime>> with Runtime a class which obiviously can't be constepxr.
But the type can be construct in several way that's why I use:
hana::tuple<hana::pair<hana::type<int>, hana::type<Runtime>>> to do the work at compile time.
So the question is basically how convert from the first tuple type to the second one. I wonder if there is something in hana that could help me. Or even better, some tips on that kind of "conversion".
namespace hana = boost::hana;
using namespace hana::literals;
struct Runtime { std::vector<int> data; };
template < typename T >
struct Foo {
T data;
};
constexpr decltype(auto) convertMap(auto storageMap) {
return hana::make_type(hana::transform(
storageMap,
[] (auto pair) {
return hana::make_pair(
hana::first(pair),
typename decltype(hana::typeid_(hana::second(pair)))::type {});
}));
}
int main() {
constexpr auto map = hana::make_tuple(
hana::make_pair(hana::type_c<int>, hana::type_c<Runtime>)
);
constexpr auto result = convertMap(map);
static_assert(result ==
hana::type_c<hana::tuple<hana::pair<hana::type<int>, Runtime>>>);
Foo<typename decltype(result)::type> test;
}
As you can see I tried some c++1z convertMap with hana::transform and lambdas, but the second tuple can't be constexpr, so I can't pass it to hana::make_type hoping to get a hana::type_c.
test.cpp: In function ‘int main()’:
test.cpp:70:41: error: ‘constexpr decltype(auto) convertMap(auto:27) [with auto:27 = boost::hana::tuple<boost::hana::pair<boost::hana::type_impl<int>::_, boost::hana::type_impl<Runtime>::_> >]’ called in a constant expression
constexpr auto result = convertMap(map);
^
test.cpp:53:27: note: ‘constexpr decltype(auto) convertMap(auto:27) [with auto:27 = boost::hana::tuple<boost::hana::pair<boost::hana::type_impl<int>::_, boost::hana::type_impl<Runtime>::_> >]’ is not usable as a constexpr function because:
constexpr decltype(auto) convertMap(auto storageMap) {
^~~~~~~~~~
test.cpp:53:27: error: temporary of non-literal type ‘boost::hana::tuple<boost::hana::pair<boost::hana::type_impl<int>::_, Runtime> >’ in a constant expression
In file included from /usr/include/boost/hana/detail/struct_macros.hpp:29:0,
from /usr/include/boost/hana/adapt_adt.hpp:15,
from lib/hana/include/boost/hana.hpp:59,
from test.cpp:1:
/usr/include/boost/hana/tuple.hpp:68:12: note: ‘boost::hana::tuple<boost::hana::pair<boost::hana::type_impl<int>::_, Runtime> >’ is not literal because:
struct tuple
^~~~~
/usr/include/boost/hana/tuple.hpp:68:12: note: ‘boost::hana::tuple<boost::hana::pair<boost::hana::type_impl<int>::_, Runtime> >’ has a non-trivial destructor
All you care about is a type - you can therefore hide the computation of the type in a non-constexpr implementation function, and afterwards call it with decltype(...){} to "force constexpr":
template <typename T>
decltype(auto) convertMapImpl(T storageMap)
{
return hana::make_type(hana::transform(storageMap, [](auto pair) {
return hana::make_pair(hana::first(pair),
typename decltype(hana::typeid_(hana::second(pair)))::type{});
}));
}
template <typename T>
constexpr decltype(auto) convertMap(T storageMap)
{
return decltype(convertMapImpl(storageMap)){};
}
live wandbox example
Also note that using auto in a function signature is a gcc extension - you should use a template parameter instead to be standard-compliant.

use type_traits to limit type of template member function

I'm writing a template class with a method that performs some bitwise operations, so I want to limit the type in the case this method is used within is_integral. I took the simple example here and modified a bit as follows:
#include <iostream>
#include <type_traits>
template <typename T>
class A
{
public:
A();
T foo(T i) {
static_assert(std::is_integral<T>::value, "Integer required.");
return (i & 2);
}
private:
T x;
};
int main() {
A<double> a;
std::cout << a.foo(3) << std::endl;
return 0;
}
However, compiler gives me 2 compile errors at static_assert():
static_assert failed "Integer required."
and at return (i & 2);:
invalid operands to binary expression ('double' and 'double')
My question is, if it will show the error at line return (i & 2); anyway, using type_traits to check for type here seems useless? And, is there anyway to throw the error to console output when it runs, instead of making it unable to be compiled?
My question is, if it will show the error at line return (i & 2); anyway, using type_traits to check for type here seems useless?
It's true that it's unfortunate that you get subsequent compile errors anyway, but which compile error do you find more readable?
"Integer required."
invalid operands to binary expression (double and double)
I know what I did wrong about the first one - I have A<double> but foo() requires an integer. No idea about the second. Am I misusing your class template or does it have a bug?
And, is there anyway to throw the error to console output when it runs, instead of making it unable to be compiled?
You want it to be a compile error. Catching errors at compile time is a lot better than catching errors at compile time.
Compiler is trying to report as many errors as it can. static_assert reports an error, but there is another error as well (using double argument for &) so it also is reported.
If you want to limit output to one error, you should have two sfinae-enabled overloads and have a second one (for anything but integrals) consist of a single static_assert.
As for your last question, the whole purpose of doing static_assert is to trigger errors at compile time, not runtime.
Here's another way to achieve the same thing. You may or may not prefer the error messages:
#include <iostream>
#include <type_traits>
template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
class A
{
public:
A();
T foo(T i) {
return (i & 2);
}
private:
T x;
};
int main() {
A<double> a;
std::cout << a.foo(3) << std::endl;
return 0;
}
sample errors:
In file included from /opt/gcc-5.3.0/include/c++/5.3.0/bits/move.h:57:0,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_pair.h:59,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/stl_algobase.h:64,
from /opt/gcc-5.3.0/include/c++/5.3.0/bits/char_traits.h:39,
from /opt/gcc-5.3.0/include/c++/5.3.0/ios:40,
from /opt/gcc-5.3.0/include/c++/5.3.0/ostream:38,
from /opt/gcc-5.3.0/include/c++/5.3.0/iostream:39,
from /tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp:1:
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits: In substitution of 'template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = std::integral_constant<bool, false>::value; _Tp = void]':
19 : required from here
/opt/gcc-5.3.0/include/c++/5.3.0/type_traits:2388:61: error: no type named 'type' in 'struct std::enable_if<false, void>'
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^
/tmp/gcc-explorer-compiler11636-75-1ve7gbt/example.cpp: In function 'int main()':
19 : error: template argument 2 is invalid
A<double> a;
^
20 : error: request for member 'foo' in 'a', which is of non-class type 'int'
std::cout << a.foo(3) << std::endl;
^
Compilation failed

C++ GCC Why this sfinae code can be compiled with GCC 4.7, but not with 4.8?

I like to use local classes in template classes to perform constructions like "static if". But I've faced with the problem that gcc 4.8 does not want to compile my code. However 4.7 does.
This sample:
#include <type_traits>
#include <iostream>
#include <string>
using namespace std;
struct A {
void printA() {
cout << "I am A" << endl;
}
};
struct B {
void printB() {
cout << "I am B" << endl;
}
};
template <typename T>
struct Test {
void print() {
struct IfA {
constexpr IfA(T &value) : value(value) {
}
T &value;
void print() {
value.printA();
}
};
struct IfB {
constexpr IfB(T &value) : value(value) {
}
T &value;
void print() {
value.printB();
}
};
struct Else {
constexpr Else(...) {}
void print() {
}
};
typename conditional<is_same<T, A>::value, IfA, Else>::type(value).print();
typename conditional<is_same<T, B>::value, IfB, Else>::type(value).print();
}
T value;
};
int main() {
Test<A>().print();
Test<B>().print();
}
Options:
g++ --std=c++11 main.cc -o local-sfinae
Task:
Given classes A and B with different interfaces for printing.
Write a generic class Test that can print both A and B.
Do not pollute either any namespace or class scope.
Description of the code:
This is only a clean example.
I use an approach like this, because I want to generalize the construction "static if". See, that I pass the arguments to IfA and IfB classes via their fields, not directly to the print() function.
I use such constructions a lot.
I've found that these constructions should not be in (pollute) class scope. I mean they should be placed in a method scope.
So the question.
This code can not be compiled with GCC 4.8. Because it checks ALL classes, even if they are never used. But it has not instantiate them in binary (I've commented the lines that cause errors and compiled it with gcc 4.8). Proof:
$ nm local-sfinae |c++filt |grep "::If.*print"
0000000000400724 W Test<A>::print()::IfA::print()
00000000004007fe W Test<B>::print()::IfB::print()
See, there is no Test::print()::IfB::print(). (See later: 'void Test::print()::IfB::print() [with T = A]')
The errors if I compile aforementioned code with gcc 4.8:
g++ --std=c++11 main.cc -o local-sfinae
main.cc: In instantiation of 'void Test<T>::print()::IfB::print() [with T = A]':
main.cc:36:9: required from 'void Test<T>::print() [with T = A]'
main.cc:49:21: required from here
main.cc:34:17: error: 'struct A' has no member named 'printB'
value.printB();
^
main.cc: In instantiation of 'void Test<T>::print()::IfA::print() [with T = B]':
main.cc:28:9: required from 'void Test<T>::print() [with T = B]'
main.cc:50:21: required from here
main.cc:26:17: error: 'struct B' has no member named 'printA'
value.printA();
^
Is it a GCC 4.8 bug?
Or is it GCC 4.7 bug? Maybe the code should not be compiled.
Or it is a my bug, and I should not rely on the compiler behavior/should not use such approach to implement "static if".
Additional info:
This simple code compiles on 4.7, but not on 4.8. I shortened it.
struct A {
void exist() {
}
};
template <typename T>
struct Test {
void print() {
struct LocalClass {
constexpr LocalClass(T &value) : value(value) {
}
T &value;
void print() {
value.notExist();
}
};
}
T value;
};
int main() {
Test<A>().print();
}
Errors:
main.cc: In instantiation of 'void Test<T>::print()::LocalClass::print() [with T = A]':
main.cc:16:9: required from 'void Test<T>::print() [with T = A]'
main.cc:22:21: required from here
main.cc:14:17: error: 'struct A' has no member named 'notExist'
value.notExist();
^
Have tested two GCC 4.8 versions: 2012.10 and 2013.02. Hope it is GCC 4.8 bug and it can be fixed.
LocalClass is not a template. The "not instantiated if not used" rule is only applicable to member functions of class templates.
That is, when Test::print() is instantiated, everything that is inside is brought to life, including the unused member of its local class.
There is no SFINAE in your code.
SFINAE applies during template argument deduction and argument substitution (the 'S' in SFINAE stands for substitution) but the only substitution in your program happens when substituting A for T in the template parameter list of Test, which doesn't fail.
You then call print() which instantiates Test<A>::print(), which doesn't involve any substitution, and you get an error because value.notExist(); is not valid.
SFINAE has to be used in substitution contexts, such as template argument deduction caused by a function call or when deducing template parameters with default arguments.

VS2012 SP1 (+november pack) unknown-type errors (alike C::a(T &&...) )

So ms compiler online could not compile this (as wall as my home VS2012 with SP1 (+november pack)) while clang and modern gcc could. Can aany one please tall me what C++11 feature is missing in VS and is there ways around?
#include <iostream>
#include <utility>
#include <type_traits>
struct A {
int x;
void a() {
std::cout << "an a! " << x << "\n";
}
};
struct B {
double x;
double b(double k) {
std::cout << "b! " << x << ", " << k << "\n";
return x - k;
}
void b() {
std::cout << "b! " << x << ", ?\n";
}
};
struct C {
A *_first__;
B *_second__;
C(A * _first__, B * _second__):_first__(_first__), _second__(_second__) {
} template < typename K, typename ... T > static auto _a_caller__(K * k, T && ... args)->decltype(k->a(std::forward < T > (args) ...)) {
return k->a(std::forward < T > (args)...);
}
template < typename...T > auto a(T &&...args)->decltype(_a_caller__(_first__, std::forward < T > (args)...)) {
return _a_caller__(_first__, std::forward < T > (args)...);
}
template < typename...T > auto a(T &&...args)->decltype(_a_caller__(_second__, std::forward < T > (args)...)) {
return _a_caller__(_second__, std::forward < T > (args)...);
}
template < typename K, typename...T > static auto _b_caller__(K * k, T && ... args)->decltype(k->b(std::forward < T > (args) ...)) {
return k->b(std::forward < T > (args)...);
}
template < typename...T > auto b(T &&...args)->decltype(_b_caller__(_first__, std::forward < T > (args)...)) {
return _b_caller__(_first__, std::forward < T > (args)...);
}
template < typename...T > auto b(T &&...args)->decltype(_b_caller__(_second__, std::forward < T > (args)...)) {
return _b_caller__(_second__, std::forward < T > (args)...);
}
};
int main() {
A a {12};
B b {24};
C c (&a, &b);
c.a();
c.b();
std::cout << c.b(2445) << std::endl;
}
Errors:
testvc.cpp
--\testvc.cpp(38) : error C2535: 'unknown-type C::a(T &&...)' : member function already defined or declared
--\testvc.cpp(33) : see declaration of 'C::a'
--\testvc.cpp(47) : error C2535: 'unknown-type C::b(T &&...)' : member function already defined or declared
--\testvc.cpp(42) : see declaration of 'C::b'
--\testvc.cpp(56) : error C2893: Failed to specialize function template 'unknown-type C::a(T &&...)'
With the following template arguments:
''
--\testvc.cpp(57) : error C2893: Failed to specialize function template 'unknown-type C::b(T &&...)'
With the following template arguments:
''
--\testvc.cpp(58) : error C2893: Failed to specialize function template 'unknown-type C::b(T &&...)'
With the following template arguments:
'int'
[This answer has been updated. See the EDIT at the end of the text]
I brought this down to an SSCCE:
#include <iostream>
struct A { A g(int) { return A(); } };
struct B { B g() { return B(); } };
struct C
{
template<typename... Ts>
auto f(Ts... ts) -> decltype(A().g(ts...))
{ std::cout << "f -> A" << std::endl; return A(); }
template<typename... Ts>
auto f(Ts... ts) -> decltype(B().g(ts...))
{ std::cout << "f -> B" << std::endl; return B(); }
};
int main()
{
C c;
c.f(1);
}
GCC 4.7.2 and Clang 3.2 compile this, while VC11 does not. Indeed it seems VC11 does not apply SFINAE when substitution fails inside the decltype expression, and this is most likely a bug.
In fact, the C++11 Standard specifies (14.8.2/7):
The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. [...]
Also relevant to SFINAE is 14.8.2/8, which adds:
If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed if written using the substituted arguments. [...] Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure.
So is this a case of substitution failure "in an immediate context"? The same paragraph clarifies what is meant by "immediate context":
Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the “immediate context” and can result in the program being ill-formed.
In the case of my simplified example, the substitution failure definitely occurs in an immediate context, as it involves no template instantiation or specialization whatsovever. Thus, VC11 definitely contains a bug.
However, it is less obvious whether in your example the substitution happens in an "immediate context", because inside the decltype expression a function template (_b_caller__) instantiation is attempted.
The key observation here is that the instantiation is attempted but never performed, because type deduction fails (again, due to substitution failure for the expression in the decltype clause of the template function whose instantiation is attempted). Thus, the error does not occur in the nested context of a template instantiation.
Hence, this qualifies as a VC11 bug.
P.S.: See this Q&A on SO for a situation where SFINAE does not apply because substitution failure occurs in a nested context.
EDIT:
It turns out my answer was incorrect, but I decided to keep its original text because I believe the reasoning is non-trivial and might be helpful to some. However, I overlooked one important aspect.
As Johannes Schaub correctly pointed out in a comment below, the second definition of f() above is ill-formed and no diagnostic is required. This is dictated by Paragraph 14.6/8 of the C++11 Standard:
[...] If every valid specialization of a variadic template requires an empty template parameter pack, the template definition is ill-formed, no diagnostic required. [...]
Thus, although the program is ill-formed, compilers are not required (even though they are allowed) to issue an error. This means that failure to compile this program is NOT a bug of VC11, but rather a good feature, in that the compiler detects an error it is not required to detect (although it must be said that the error message is quite misleading).
That's complicated. I guess, GCC and CLANG are using SFINAE to disambiguate the two function templates, that at first glance are ambiguos. Lets look at an example: The call c.b(2445) I'm gonna mess up a bit the types and actual arguments, but I hope it's understandable what I mean.
Instantiating the first function template, meaning
auto b<int>(int args)->decltype(_b_caller__(_first__, std::forward <int> (args))), which in turn instantiates _b_caller<A,int>, which calls _first__->b(int). Since A has no method b, both instantiations fail. This leads to
Instantiating the second function template, meaning
auto b<int>(int args)->decltype(_b_caller__(_second__, std::forward <int> (args))) and _b_caller<B,int> which works, since B has a method b(double).
It seems that somewehere in that process Visual Studio bails out. My guess is, that SFINAE does not work correctly with trailing return types, but it might as well be the two level deep instantiation that makes it difficult to apply SFINAE correctly in that case.
Edit: this might be related:
Why does SFINAE not apply to this?