There is such function definition:
template<>
template<>
void object::test<1>()
{
}
What does it mean that there are double template<>?
EDIT:
I extracted code which is valid for this example:
#include <iostream>
template <class U>
class A {
template <int n>
void test() {
}
};
template <class T>
class B {
public:
typedef A<T> object;
};
typedef B<int>::object object;
template<>
template<>
void object::test < 1 > () {
}
int main() {
return 0;
}
This code compiles under g++.
Source: TUT test framework
For example,
template<class T = int> // Default T is int
class object<T> {
template<int R> void test ();
};
Your code:
template<> // T is fixed
template<> // R is fixed
void object<>::test<1>() // T is default int, R is 1
{
}
is equivalent to:
template<> // T is fixed
template<> // R is fixed
void object<int>::test<1>() // T is int, R is 1
{
}
This is the template specialization of a class template member function template (did I get that right?), with a default parameter for the template. Look at this:
template<typename T = int>
struct X {
template<typename U>
void foo(U u);
};
template<>
template<>
void X::foo(float f) { }
This introduces a specialization for the case where the template parameter of X is int and the argument to X<int>::foo is float. This case is slightly different from yours, we don't have to provide the template argument explicitly after the name of the member function as it can be deduced. Your function has a non-type template argument which cannot be deduced and as such must be provided.
What confused me the most is the default template argument and I'm unsure if it is good practice to use skip it. I'd provide it for every specialization to avoid confusion.
That looks to me like a specialization of a function template within a class template. For example, consider the following class template definition:
template <int m=1>
class object
{
public:
template <int n>
void test();
};
// This differs from your example, by the addition of `<>` after `object`, but it's as
// close as I can come to valid code true to your example
template<>
template<>
void object<>::test<1>()
{
}
Related
There is a template class A with template parameter T. I want this class to have a method f if T is of integral types. The class A also has a lot of other methods, so I don't want to have specialization of overall A.
I understand that this problem can be solved using inheritance, but my question is about concepts and requirements.
This code
template <typename T>
struct A {
void f();
};
template <>
void A<int>::f() {}
works as I expect. It makes implementation of f for the int type only. If I try to call A<std::string>{}.f(); it generates a linker error as expected.
But if I write
template <typename T>
struct A {
void f();
};
template <std::integral T>
void A<T>::f() {}
either
template <typename T> requires std::is_integral_v<T>
void A<T>::f() {}
the method f is generated for all types, so calling A<std::string>{}.f(); does not give any error.
Also this works
template <typename T>
struct A {
void f() {}
};
template <>
void A<std::string>::f() = delete;
but this
template <typename T>
struct A {
void f() {}
};
template <std::integral T>
struct A<T>::f() = delete;
gives compilation error, namely redefinition of f.
P.S. It seems such constructions are not allowed at all, but g++ just ignores concepts in definition of method f.
There are four syntactical methods of applying constraints to a function.
Type constraint in a template parameter list; template< Concept TypeID >.
Requires clause after a template parameter list; template< class TypeID > requires constexpr-andor-requires-expression.
Constraint on auto in an abbriviated function template; void f(Concept auto id);.
Requires clause after a function declaration; template< class TypeID > void f() requires constexpr-andor-requires-expression.
The function you want to constrain doesn't have a template parameter list so you can't use methods 1 and 2. Method 3 essentially generates template parameters. So that leaves method 4.
#include <concepts>
template< class T >
struct A {
void f() { /* do something */ }
void g() requires std::integral<T> { /* do something */ }
void h() requires std::integral<T>;
template< std::integral U = T >
void i() { /* do something */ }
};
template< class T >
void A<T>::h() requires std::integral<T> { /* do something */ }
int main() {
A<double> dblA;
dblA.f();
// dblA.g(); // A<double>::g() is not declared or defined
// dblA.h(); // A<double>::h() is not declared or defined
// dblA.i(); // A<double>::h<double>() is not declared or defined
dblA.i<int>(); // A<double>::h<int>() is declared and defined
A<int> intA;
intA.f();
intA.g(); // A<int>::g() is declared and defined
intA.h(); // A<int>::h() is declared and defined
intA.i(); // A<int>::h<int>() is declared and defined
//intA.i<double>(); // A<int>::h<double>() is not declared or defined
return 0;
}
You have to add a new template parameter, which will default to T and to which you can add your constraint of std::integral<>. This compiled with gcc10.3.0 and clang12.0.0, other versions you will have to test yourself.
The code:
#include <concepts>
#include <string>
template <typename T>
struct A
{
template <typename U = T>
requires std::integral<U>
void f();
};
template <typename T>
template <typename U>
requires std::integral<U>
void A<T>::f()
{
}
int main()
{
A<int> a;
a.f();
A<std::string> s; // This works
// s.f(); // Compilation error: constraint not satisfied
return 0;
}
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic
By using template template parameters one can pass to a class a templated class without specifying types on its parameters. I was wondering is there a way to pass into a template template parameter a templated signature of a function to be able to specialize which variant of the function is to be considered forward.
To be clear - I know I cannot do that:
template <class T>
void foo() { /*...*/ }
template <template <class...> class FooType>
struct Foo { /*...*/ };
int main() {
Foo<decltype(foo)> f;
}
But somehow I would like to be able to pass templated signature of function to Foo. Is it even possible?
I couldn't believe that this is not possible so I searched a bit and found a way to do exactly what I wanted. I used templated using with a syntax:
template <template<class... Args> class FooType>
struct Foo {
FooType<int> ft;
};
template <class Res, class... Args>
using FooSignature = Res(*)(Args...);
int foo() {
return 1;
}
int main() {
Foo<FooSignature> f;
f.ft = foo;
}
This however still leaves the question how can this be possible since the standard states something opposite.
In the example below one has a template template parameter that accepts the preferred signature for the function.
Because of the specialization and the lack of a body for the template class, only types for callables are accepted.
It is a generalization of what the OP actually asked:
#include<cassert>
template<typename F>
struct S;
template<typename R, typename... Args>
struct S<R(Args...)> {
using type = R(*)(Args...);
};
template<template<typename> class F>
struct T {
typename F<void(int)>::type ft;
typename F<double(double, double)>::type gt;
};
void f(int) { }
double g(double x, double y) { return x+y; }
int main() {
T<S> t;
t.ft = f;
t.gt = g;
t.ft(42);
auto v = t.gt(1., 1.);
assert(v == 2.);
}
As can be seen in this answer
Template of function pointer is illegal in C++
The C++ Standard says in $14/1,
A template defines a family of classes or functions.
Further quoting from the linked answer:
Please note that it does NOT say "A template defines a family of classes, functions or function pointers"
However, you can pass concrete function pointers, and specialise on their signature:
#include <iostream>
template <class T>
void foo(T) { }
template <typename>
struct Foo;
template<typename T>
struct Foo<void(T)>
{
void cb() { std::cout << "T\n"; }
};
template<>
struct Foo<void(int)>
{
void cb() { std::cout << "int\n"; }
};
template<>
struct Foo<void(double)>
{
void cb() { std::cout << "double\n"; }
};
int main()
{
Foo<decltype(foo<int >)>().cb(); // outputs 'int'
Foo<decltype(foo<double>)>().cb(); // outputs 'double'
Foo<decltype(foo<char >)>().cb(); // outputs 'T'
return 0;
}
template of template is still a template.
template <class T>
void foo() { /*...*/ }
template <typename T>
struct Foo { /*...*/ };
int main() {
Foo<decltype(foo<int>)> f;
}
You cannot pass a function template as an argument. What you can do is wrap a function template in a generate lambda taking a tag parameter:
template <class T> struct tag_t { using type = T; };
template <class T>
void foo() { ... }
template <class F>
void call_func_with(F f) {
f(tag_t<int>{} );
f(tag_t<double>{} );
}
call_with_func([](auto tag) { foo<decltype(tag)::type>(); } );
Here, f(tag_t<X>{} ) ends up calling foo<X>(), as desired.
The following code:
template <typename S, typename T>
struct foo {
void bar();
};
template <typename T>
void foo <int, T>::bar() {
}
gives me the error
invalid use of incomplete type 'struct foo<int, T>'
declaration of 'struct foo<int, T>'
(I'm using gcc.) Is my syntax for partial specialization wrong? Note that if I remove the second argument:
template <typename S>
struct foo {
void bar();
};
template <>
void foo <int>::bar() {
}
then it compiles correctly.
You can't partially specialize a function. If you wish to do so on a member function, you must partially specialize the entire template (yes, it's irritating). On a large templated class, to partially specialize a function, you would need a workaround. Perhaps a templated member struct (e.g. template <typename U = T> struct Nested) would work. Or else you can try deriving from another template that partially specializes (works if you use the this->member notation, otherwise you will encounter compiler errors).
Although coppro mentioned two solutions already and Anonymous explained the second one, it took me quite some time to understand the first one. Maybe the following code is helpful for someone stumbling across this site, which still ranks high in google, like me. The example (passing a vector/array/single element of numericalT as dataT and then accessing it via [] or directly) is of course somewhat contrived, but should illustrate how you actually can come very close to partially specializing a member function by wrapping it in a partially specialized class.
/* The following circumvents the impossible partial specialization of
a member function
actualClass<dataT,numericalT,1>::access
as well as the non-nonsensical full specialisation of the possibly
very big actualClass. */
//helper:
template <typename dataT, typename numericalT, unsigned int dataDim>
class specialised{
public:
numericalT& access(dataT& x, const unsigned int index){return x[index];}
};
//partial specialisation:
template <typename dataT, typename numericalT>
class specialised<dataT,numericalT,1>{
public:
numericalT& access(dataT& x, const unsigned int index){return x;}
};
//your actual class:
template <typename dataT, typename numericalT, unsigned int dataDim>
class actualClass{
private:
dataT x;
specialised<dataT,numericalT,dataDim> accessor;
public:
//... for(int i=0;i<dataDim;++i) ...accessor.access(x,i) ...
};
If you need to partially specialise a constructor, you might try something like:
template <class T, int N>
struct thingBase
{
//Data members and other stuff.
};
template <class T, int N> struct thing : thingBase<T, N> {};
template <class T> struct thing<T, 42> : thingBase<T, 42>
{
thing(T * param1, wchar_t * param2)
{
//Special construction if N equals 42.
}
};
Note: this was anonymised from something I'm working on. You can also use this when you have a template class with lots and lots of members and you just want to add a function.
If you're reading this question then you might like to be reminded that although you can't partially specialise methods you can add a non-templated overload, which will be called in preference to the templated function. i.e.
struct A
{
template<typename T>
bool foo(T arg) { return true; }
bool foo(int arg) { return false; }
void bar()
{
bool test = foo(7); // Returns false
}
};
In C++ 17, I use "if constexpr" to avoid specialize (and rewrite) my method. For example :
template <size_t TSize>
struct A
{
void recursiveMethod();
};
template <size_t TSize>
void A<TSize>::recursiveMethod()
{
if constexpr (TSize == 1)
{
//[...] imple without subA
}
else
{
A<TSize - 1> subA;
//[...] imple
}
}
That avoid to specialize A<1>::recursiveMethod().
You can also use this method for type like this example :
template <typename T>
struct A
{
void foo();
};
template <typename T>
void A<T>::foo()
{
if constexpr (std::is_arithmetic_v<T>)
{
std::cout << "arithmetic" << std::endl;
}
else
{
std::cout << "other" << std::endl;
}
}
int main()
{
A<char*> a;
a.foo();
A<int> b;
b.foo();
}
output :
other
arithmetic