Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

May a member function template specialization have a different access level than the main template?

An answer to a a question I had about deleting functions mentioned how member function templates can't be specialized at class scope. That led me to wonder if it's possible for a member function template specialization to have a different access level than the main template. In the code below, I'm trying to have a private specialization of a public member function template:

#include <iostream>

class Foo {
public:
  template<typename T>
  void func(T) { std::cout << "Public\n"; }

private:
  template<>
  void func<char>(char) { std::cout << "Private\n"; }

  friend int main();
};

int main()
{
  Foo f;
  f.func(10);
  f.func('a');
}

With the latest MSVC, this compiles, runs, and produces the expected output:

Public
Private

With g++ 4.8 and Clang 3.2, the code is rejected. Clang says this:

error: explicit specialization of 'func' in class scope
void func<char>(char) { std::cout << "Private\n"; }
     ^

Presumably g++ and Clang are using 14.7.3/2 of C++11 as the basis for their behavior, but I think there might be a little wiggle room, because 3.3.6/3 says that the global scope is a namespace, and the global namespace (indirectly) encloses the template specialization.

My question isn't about these parts of the Standard or about any of these compilers' behaviors, though, it's about whether it is possible for a member function template to have a specialization that has a different access level than the general template. For example, is it possible to have a public member function template and a private specialization of that template?

like image 521
KnowItAllWannabe Avatar asked Jan 09 '14 23:01

KnowItAllWannabe


People also ask

What is function template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

What is the specialty of a template function give example?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

Are template specializations inline?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is meant by template specialization Mcq?

Explanation: Template specialization is used when a different and specific implementation is to be used for a specific data type. In this program, We are using integer and character.


1 Answers

We can always do it manually.

Some random SFINAE machinery:

#include <iostream>
#include <utility>
#include <type_traits>

template<typename T> constexpr bool IsInt() { return std::is_same<T,int>::value; }
template<std::size_t>
struct SecretEnum {
  enum class hidden {};
};
template<bool b, int i=1> using EnableIf = typename std::enable_if<b,typename SecretEnum<i>::hidden>::type;

class Foo {
public:
  template<typename T, EnableIf< !IsInt<T>(), 1 >...>
  void func(T) { std::cout << "Public\n"; }

private:
  template<typename T, EnableIf< IsInt<T>(), 2 >...>
  void func(T) { std::cout << "Private with int\n"; }

  friend int main();
};

int main()
{
  Foo f;
  f.func(10);
  f.func('a');
}

now this trick does not work with clang because of how I did the SFINAE and method distinguishing last I checked. But that can be replaced with other similar tricks (like pointer based default arguments in the second argument -- replace EnableIf< IsInt<T>(), 2 >... with EnableIf< IsInt<T>(), 2 >* = nullptr or somesuch for clang. I just find it less appealing.)

So what is going on above? I have two different overloads for func. Both are template functions with one argument that is a T, and a pack of some secret enum whose type is valid if and only if T matches the IsInt<T>() or !IsInt<T>() test respectively. The type of the packs differ in the two cases (one if them is SecretEnum<2>::hidden, the other is SecretEnum<1>::hidden), so their signatures are sufficiently different to satisfy most C++11 compilers (clang considers them to be identical last I checked, generating errors, I believe clang is wrong).

When you invoke func<blah>, it checks to see which (if any) of the two func are appropriate. As their conditions are exact opposites of each other, only one of them is ever the proper one.

In effect, we are doing manual specialization.

In C++1y, we may be able to template<IsInt T> and template<IsNotInt T> if the stars align properly and the concepts lite that gets into the technical report lets this work.

like image 127
Yakk - Adam Nevraumont Avatar answered Oct 13 '22 00:10

Yakk - Adam Nevraumont