I'm have a nested (Inner
) class, for which I want to enable_if
a constructor, depending on how many template parameters (Args
) the enclosing class (Outer
) has.
I came up with the code below, only to find out that it compiles fine on some compilers, and on some not.
#include <tuple>
#include <type_traits>
template <typename... Args>
struct Outer {
struct Inner {
Inner(const Outer* out, Args... vals)
: outer(out)
, values(vals...)
{}
// This ctor should be enabled only if Args are non-empty
template <typename = std::enable_if_t<(sizeof...(Args) > 0)>>
Inner(const Outer* out)
: outer(out)
{}
const Outer* outer;
std::tuple<Args...> values;
};
};
int main()
{
Outer<int, int> o1;
Outer<int, int>::Inner i1(&o1, 1, 2);
Outer<int, int>::Inner i11(&o1);
Outer<> o2;
Outer<>::Inner i2(&o2);
Outer<>::Inner i21(nullptr);
}
Shown on Godbolt: https://godbolt.org/z/lsivO9
The funny part are the results:
GCC 8.2 -std=c++17
- FAIL to compileGCC trunk -std=c++17
- OKMSVC 19.14 /std:c++17 /permissive-
- OKMSVC 19.16 /std:c++17 /permissive-
- OKclang 7 -std=c++17
- FAIL to compileclang trunk -std=c++17
- FAIL to compile
So, the questions:
- Are the
Args...
of theOuter
class in the immediate context of theInner
class? - Is the above example well-formed?
- Which compiler is right?
- Why GCC started to behave differently with trunk?
Aucun commentaire:
Enregistrer un commentaire