Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with SFINAE in Ideone?

Tags:

c++

c++11

I'm trying to debug an issue I'm getting with Visual Studio by comparing the output of Visual Studio with the output of GCC, but I can't seem to get an extremely simplified version of the code to compile in Ideone:

#include <exception>
#include <iostream>

template <int x>
struct foo {};

template <>
struct foo<0> { using type = int; };

template <typename Foo>
struct bar
{
    bar(void) {}

    template <typename = typename Foo::type>
    bar(const bar &) {}
};

int main(void)
{
    bar<foo<1>> x;
}

The above gives me the error when I try to run it using Ideone:

prog.cpp: In instantiation of ‘struct bar<foo<1> >’:
prog.cpp:21:17:   required from here
prog.cpp:16:5: error: no type named ‘type’ in ‘struct foo<1>’
     bar(const bar &) {}

From my understanding, the failure to substitute Foo::type should not result in a compilation error. Note that making the copy constructor bar(const bar &) { typename Foo::type x; } allows the program to compile just fine. I'm trying to use this template in pretty much the exact same way that std::enable_if is used, which also causes compilation errors when used anywhere within the class - not just on the copy constructor. Is this correct behavior? I'm fairly certain it's not, but I've always thought that Ideone uses GCC in the back-end...

like image 812
Duncan Avatar asked Feb 01 '26 06:02

Duncan


1 Answers

Yes this behavior is correct.

SFINAE applies when deducing template parameters during function template overload resolution (the compiler is allowed to discard a specialization without emitting an error).

In your case the error did not occur during overload resolution, but during the template instantiation : the bar template simply cannot be instantiated, since the copy constructor requires the existence of the nested type Foo::type, which doesn't exist when the template parameter is foo<1>.

For your last point, if you declare :

template <typename Foo>
struct bar
{
    bar(void) {}

    bar(const bar &) { typename Foo::type x; }
};

It compiles fine as long as you don't call the copy constructor. Using the copy constructor will cause the same compilation error :

bar<foo<1>> x2 = x; // Error
like image 123
quantdev Avatar answered Feb 02 '26 22:02

quantdev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!