0

I'm trying to alias the type which is located in a class located in the base class's body.

Sample code:

#include <iostream>
#include <typeinfo>
#include <type_traits>


template <typename...Ts>
    struct X;

template <typename T, typename...Ts>
    struct X<T, Ts...> : X<Ts...>
{
    using base = X<Ts...>;

    template <typename R, int I=0>
        struct find
    {
        using type = base::template find<T, I+1>;
    };

    template <int I>
        struct find<T, I>
    {
        using type = X;
    };
}

template <>
    struct X<>
{};

int main()
{
    using type = X<int, float>;

    std::cout << typeid(type::find<float>).name();
}

This produced an error error: expected a type for line:

using type = base::template find<T, I+1>;

What have I done wrong?

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • 4
    _But it doesn't seem to work._ [Does not work](http://importblogkit.com/2015/07/does-not-work/) is not an useful problem description. – Algirdas Preidžius Mar 21 '17 at 19:16
  • I don't understand. The problem description is in the subject. – Adrian Mar 21 '17 at 19:17
  • 2
    @Adrian What you want to do is in the description. But then, you are referring to your problem as _doesn't seem to work_, or _why is this not valid_. But then, fail to mention _how_ it doesn't seem to work. Are you getting compilation error? If so, what is the error message? This sort of information is not present in the question itself, but it should be. – Algirdas Preidžius Mar 21 '17 at 19:21
  • Thanks @AlgirdasPreidžius. I've updated the question. This sample shows the error that I had found in my production code, but adding the `typename` keyword didn't work there. That was the first thing I had tried before coming to SO. Seems that I prolly have some other syntax error that is causing me to go on a wild goose chase. – Adrian Mar 21 '17 at 19:31
  • Is that the exact error? I would have expected a more verbose error message from either gcc or Visual Studio. – drescherjm Mar 21 '17 at 19:37
  • @drescherjm, yes, that is the exact error from clang. There was a 2ndary error, but that was a cascade error indicating there should be a `;` after base. – Adrian Mar 21 '17 at 19:40
  • @Adrian Then, there's something else wrong with your production code, and we are not mind readers. If you don't tell us about the issue - we cannot help you to solve it. When I fixed missing semicolon (`;`) after `struct` definition, I [could reproduce](http://ideone.com/ZPN0w8) your issue with the posted code, but the error disappears when [I add `typename` in appropriate place](http://ideone.com/Z369Uy), as the answer suggested. You have other, unrelated, issue, about which, you didn't provide _any_ details. – Algirdas Preidžius Mar 21 '17 at 19:42
  • Interesting. Here is the gcc build:http://ideone.com/BpUquF and the Visual Studio one: http://rextester.com/AMEFS68849 – drescherjm Mar 21 '17 at 19:42
  • @AlgirdasPreidžius, that's very helpful. 9.9 I had thought that I had reproduced the problem, and I was wrong. There's no need to snippy. I'm not a n00b on this forum, but I am human and I do make mistakes. Move on. – Adrian Mar 21 '17 at 20:01
  • @Adrian 1) SO is **not** a forum (as you already pointed out - you should know that). 2) I didn't say that you were. I just pointed out the initial issues with your question, and, once those were fixed, I pointed out that if the answer doesn't answer your question - the issue is somewhere else. No need to get offended over criticism. – Algirdas Preidžius Mar 21 '17 at 22:04

1 Answers1

4

You're missing a typename because base::find is a dependant type:

#include <iostream>
#include <typeinfo>
#include <type_traits>


template <typename...Ts>
struct X;

template <typename T, typename...Ts>
struct X<T, Ts...> : X<Ts...>
{
    using base = X<Ts...>;

    template <typename R, int I=0>
    struct find
    {
        using type = typename base::template find<T, I+1>;
    };

    template <int I>
    struct find<T, I>
    {
        using type = X;
    };
};

template <>
struct X<>
{};

int main()
{
    using type = X<int, float>;

    std::cout << typeid(type::find<float>).name();
}

There'a a little more work to do though, check the output.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
  • I've tried that. Using `typename base::template find` doesn't work either. – Adrian Mar 21 '17 at 19:20
  • 2
    Yes, it does, you just also missed a semicolon in there too, fix that and you should be good to go. – Andria Mar 21 '17 at 19:21
  • Ah right. Thanks. – Adrian Mar 21 '17 at 19:23
  • This didn't fix my problem in my production code. That was the first thing I tried before coming to SO, so it must be some syntax error that is messing up stuff and emitting an error that isn't what is actually wrong. – Adrian Mar 21 '17 at 19:33
  • 2
    @Adrian If not, then your [mcve] is wrong. Obviously, the same problem has the same solution, and if this solution fixes the problem in your question, but not the original question, then your example reproduces another error. – Rakete1111 Mar 21 '17 at 19:41
  • @Rakete1111, yes, I know. I posted this because I had thought I had reproduced the error. In that I was mistaken. However, the question may still be useful to others. – Adrian Mar 21 '17 at 19:42
  • What I find curious is, given it's location, why doesn't the compiler infer that it must be a type, rather than have the user explicitly state it. It's not like you are going to define a type alias and assign it a value. I also find the use of the keyword `template` also superfluous in that context. It just adds to the noise. – Adrian Mar 21 '17 at 19:51