C++1y/C++14: Variable Template Specialization?

2019-03-10 19:00发布

According to C++1y/C++14 N3690, does the type of a variable template specialization have to be the same as the type of the primary template?

template<int x>
char y = f(x);

template<>
double y<42> = g();

And if so, is it possible to leave the primary undefined somehow?

template<int x>
???? y = ???; // undefined

template<>
double y<42> = g();

Where is this covered in the draft?

The equivalent functionality for a class template would be:

template<int x>
struct S
{
    static char y;
};

template<>
struct S<42>
{
    static double y;
};

and

template<int x>
struct S; // undefined

template<>
struct S<42>
{
    static double y;
};

4条回答
我只想做你的唯一
2楼-- · 2019-03-10 19:20

It's a bit risky to extrapolate that Clang is expressing the feature intended for standardization. (NB: I didn't refer to anything for this answer.)

Of course the fallout from allowing a change of type is that you can't specialize the template after it's been referenced in any way, whereas for all other kinds of templates the cutoff time is at ODR-use. Unless they're planning something wacky, this looks like a Clang bug.

You can always use a type template to declare the type of the variable template.

template< typename t >
struct x_type { typedef … type; };

template< typename t >
typename x_type< t >::type x = …;

Now x_type may be specialized. This just guards against the possibility that Clang is currently buggy. It doesn't allow you to refer to an object of indeterminate type. C++ just doesn't support that. Referring to the object ODR-uses the class template specialization.

查看更多
劳资没心,怎么记你
3楼-- · 2019-03-10 19:33

Does the type of a variable template specialization have to be the same as the type of the primary template?

No, an explicit (or partial) specialization of a variable template can specify a type different from the type that would be implied by an implicit instantiation. When implementing the feature for Clang, we discovered that the specification had no rule requiring the type to match in this case, and we brought the issue to the C++ core working group, where it was confirmed that this omission was intentional.

Is it possible to leave the primary undefined somehow?

It is not possible to declare the primary variable template without specifying at type -- there is no syntax that would allow such a thing.

Where is this covered in the draft?

Both of these are covered by omission -- there is no rule requiring the types to match, and there is no syntax for declaring a variable template without a type. So I can't point you at any particular part of the standard and say "here's where the rule isn't".

If you have access to the C++ standard committee's reflectors, see the thread starting with core-23901 for the discussion of this.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-03-10 19:33

The following compiles with clang trunk -std=c++1y:

#include <iostream>

template<int x>
char y = 3;

template<>
double y<42> = 2.5;

char c {y<17>};

double d {y<42>};

So either a specialization of a variable template doesn't need to have the same type as its primary, or clang has a buggy implementation of N3690

查看更多
做个烂人
5楼-- · 2019-03-10 19:33

I would fully expect that the declaration of a specialization needs to match the primary template exactly, including its type. This isn't anything new for variable templates. I haven't chased down the details in the standard, yet, to see where it specifies this detail.

The code below seems to do something akin to what you want, i.e., leave the variable type sort of open:

#include <iostream>

template <int X> struct var_type { typedef int type; };
template <> struct var_type<42> { typedef double type; };

int    f(int x) { return x; }
double g()    { return 3.14; }

template <int X>
typename var_type<X>::type var = f(X);
template <>
typename var_type<42>::type var<42> = g();

int main()
{
    std::cout << "var<17>=" << var<17> << '\n';
    std::cout << "var<42>=" << var<42> << '\n';
}
查看更多
登录 后发表回答