Why does gcc complain "error: type 'intT' of template argument '0' depends on a template parameter"?
Asked Answered
E

2

3

My compiler is gcc 4.9.0. The following code cannot be compiled:

template<typename T, T i>
struct value {};

template<typename T>
struct value<T, 0> {};
// error: type 'T' of template argument '0' depends on a template parameter

What is the cause? and, how to solve this issue?

Establishmentarian answered 9/7, 2014 at 14:18 Comment(1)
How to solve this issue? -> see the answers to the following questions for some workarounds: (Partially) specializing a non-type template parameter of dependent type and Dependant non-type template parameter and variadic template.Addis
M
8

GCC is right, this is explicitly forbidden by C++11 [temp.class.spec] §8:

8 Within the argument list of a class template partial specialization, the following restrictions apply:

  • A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier. [ Example:

    template <int I, int J> struct A {};
    template <int I> struct A<I+5, I*2> {}; // error
    template <int I, int J> struct B {};
    template <int I> struct B<I, I> {}; // OK
    

    —end example ]

  • The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example:

    template <class T, T t> struct C {};
    template <class T> struct C<T, 1>; // error
    template< int X, int (*array_ptr)[X] > class A {};
    int array[5];
    template< int X > class A<X,&array> { }; // error
    

    —end example ]

  • ...

I believe point 2 is the most relevant one here.


Regarding the question of "how to solve this issue." In the form the question stands now, there is no workaround, I am afraid.

As for the original vesion with making integer sequences, I believe that you could make it work with using uintmax_t for the type of the non-type template parameter, and only convert it to intT in the final definition.

Mucous answered 9/7, 2014 at 14:27 Comment(10)
Where is the solution?Establishmentarian
@Angew: Goodness, I battled at it and it was really stubborn... glad you managed it!Inoffensive
@Establishmentarian You asked why it doesn't work, not how to make it work. The shortened version of your question has a simple answer "this cannot work." The original one might have a different solution, though. Still, the question was "why?"Mucous
@MatthieuM. I sometimes forget how badly copies from the standard PDF look unedited.Mucous
@xmllmx: The solution involves not using partial specialization I would guess. Do you actually need those integer sequences you were mentioning ? They already exist in C++14 (see here).Inoffensive
@MatthieuM. I just want to know how C++14's integer_sequence works.Establishmentarian
@xmllmx: llvm.org/svn/llvm-project/libcxx/trunk/include/utility (search for integer_sequence and do not stop on the first few hits which are part of the sum-up of what the header contains).Inoffensive
@MatthieuM. I think clang's implementation is ugly. I'm learning gcc's.Establishmentarian
LLVM's implementation is quite strange, GNU's is shorter and easier to read, looking more like the "obvious" implementation: gcc.gnu.org/git/?p=gcc.git;a=blob_plain;f=libstdc%2B%2B-v3/…Rudiger
@Oktalist: libc++'s implementation is optimized to reduce the number of recursive steps which in turns speeds up computation. This does not matter, however, what matters is the __convert trick: the recursion is done on a fixed type (size_t) and then the integers are converted to another type depending on what was asked.Inoffensive
A
0

use std::integral_constant instead of a integer literal directly:

template<typename T, typename VALUE>
struct value;

template<typename T>
struct value<T, std::integral_constant<T, 0> >
{
};

this worked fine for me, when trying to implement std::make_integer_sequence for C++11....

Asp answered 6/2, 2020 at 21:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.