I have a template
template<size_t N>
class Foo {
int bar(int a) {
if (N == 0)
return 0;
return a / N;
}
}
when I instantiate this with 0
Foo<0> bar;
gcc is too smart and reports division by zero at compile time
I tried
class Foo<size_t N> {
template<size_t M>
int bar(int a) {
return a / N;
}
template<>
int bar<0>(int a) {
return 0;
}
};
but this gives me error:
error: explicit specialization in non-namespace scope 'class Foo'
error: template-id 'bar<0>' in declaration of primary template
any ideas how I could solve/workaround this?
You can always rethink the formula:
template<size_t N>
class Foo {
bool bar() {
return N == 0 || (N >=5 && N < 10);
}
}
You can create a template specialization for Foo<0>.
template <>
class Foo<0> {
public:
bool bar () { return true; }
};
If you only want to address the issue with bar alone, and not touch any other part of Foo, you can create a companion method to avoid the issue:
template <size_t N>
class Foo
{
bool bar(int n) {
if (n == 0) return true;
return 5 / n == 1;
}
public:
bool bar() { return bar(N); }
};
Or pull the implementation of that method out into its own class, and specialize that:
template <size_t N>
class Bar
{
public:
bool operator() const { return 5 / N == 1; }
};
template <>
class Bar<0>
{
public:
bool operator() const { return true; }
};
template <size_t N>
class Foo {
bool bar() { return Bar<N>()(); }
};
Alternatively, you can use Jarod42's suggestion, and specialize the method itself (answer reiterated here for completeness).
template <size_t N>
class Foo
{
public:
bool bar() { return 5 / N == 1; }
};
template <> inline bool Foo<0>::bar() { return true; }
You may specialize the method:
template <size_t N> class Foo
{
public:
bool bar()
{
return 5 / N == 1;
}
};
template <>
bool Foo<0>::bar() { return true; }
Live example
To avoid multiple definitions, you have to define the function only once, or use inline, so
// In header
template <>
inline bool Foo<0>::bar() { return true; }
or
// In header: declaration of the specialization
template <>
bool Foo<0>::bar();
// in cpp: definition of the specialization.
template <>
bool Foo<0>::bar() { return true; }
Related
I'm trying to understand the reason for the compilation error with my CRTP implementation in this example:
template<class T>
struct Interface
{
static constexpr int func();
static constexpr int func2();
};
template<class T>
struct Default : public Interface<T>
{
constexpr static int impl_func()
{
return 0;
}
constexpr static int impl_func2()
{
return Default<T>::func() + 2; <----------- (A)
}
};
struct Derived : public Default<Derived>
{
static constexpr int impl_func2()
{
// NOTE: Using impl_func instead of func here compiles
return func() + 4; <-------------- (B)
}
};
struct Derived2 : public Default<Derived2>
{
};
template <typename T> constexpr int Interface<T>::func()
{
return T::impl_func();
}
template <typename T> constexpr int Interface<T>::func2()
{
return T::impl_func2();
}
int main()
{
constexpr int ret = Derived::func2();
static_assert(ret == 4);
constexpr int ret2 = Derived2::func2();
static_assert(ret2 == 2);
}
Specifically why is (A) ok while (B) gives me this error:
test3.cpp:45:19: error: constexpr variable 'ret' must be initialized by a constant expression
constexpr int ret = Derived::func2();
^ ~~~~~~~~~~~~~~~~
test3.cpp:29:16: note: undefined function 'func' cannot be used in a constant expression
return func() + 4;
Replacing (B) with return impl_func() + 4 compiles successfully. But neither Derived::func() nor Default<Derived>::func() work. If (B) needs to be impl_func() then is there something different about the fact that (A) is in a templated class that allows it to compile successfully?
With constexpr function, definition should be available when used...
reordering function definition solve the issue:
template<class T>
struct Interface
{
static constexpr int func();
static constexpr int func2();
};
template <typename T> constexpr int Interface<T>::func()
{
return T::impl_func();
}
template <typename T> constexpr int Interface<T>::func2()
{
return T::impl_func2();
}
// Remaining code.
Demo
I'm working on a C++11 wrapper around a C api. The C api offers a bunch of getters for various types, with a different name for each type. Values are retrieved by array of a given size, known at compilation.
I want to give the type and the array size by template, to call the right function.
#include <string>
#include <iostream>
template <typename T>
struct make_stop {
constexpr static bool value = false;
};
class Foo
{
public:
Foo() : i(42) {}
template<typename T, size_t n>
T get();
private:
int i = 0;
};
template<typename T, size_t n>
T Foo::get() { static_assert(make_stop<T>::value); return T(); }
template<int, size_t n>
int Foo::get() { return i + n; }
int main() {
Foo foo;
int i = foo.get<int, 4>();
double f = foo.get<double, 2>();
return 0;
}
But it fails to match the right function
main.cpp:26:5: error: no declaration matches 'int Foo::get()'
int Foo::get() { return i + n; }
^~~
main.cpp:15:7: note: candidate is: 'template<class T, long unsigned int n> T Foo::get()'
T get();
its a bit vauge from your question, but assuming you are wanting to index into some c- arrays and return the value at I you can't specialize function templates like you want, but you can use some tags instead, something like..
class Foo
{
public:
Foo() : is{1,2,3,4,5,6,7,8,9,10},ds{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1} {}
template <typename T> struct type_c{};
template <size_t I> struct int_c{};
template<typename T,size_t I>
auto get()
{ return get_impl(type_c<T>(),int_c<I>()); }
private:
template <size_t I>
auto get_impl(type_c<int>,int_c<I>)
{ return is[I]; }
template <size_t I>
auto get_impl(type_c<double>,int_c<I>)
{ return ds[I]; }
int is[10];
double ds[10];
};
int main() {
Foo foo;
int i = foo.get<int,0>();
double d = foo.get<double,2>();
std::cout << i << " " << d << std::endl;
return 0;
}
Demo
If I understood you correctly you want to partially specialize get for T. Unfortunately partial specialization for methods is not allowed by the standard. You can however get around this with a static method on a class templated by T and specializing the class.
Like this:
template <class T> struct Foo_helper;
struct Foo
{
Foo() : i{42} {}
template<class T, std::size_t N>
T get()
{
return Foo_helper<T>::template get<N>(*this);
}
int i = 0;
};
template <class T> struct Foo_helper {};
// specialize Foo_helper for each type T you wish to support:
template <> struct Foo_helper<int>
{
template <std::size_t N>
static int get(const Foo& foo) { return foo.i + N; }
};
template <> struct Foo_helper<double>
{
template <std::size_t N>
static double get(const Foo& foo) { return foo.i + N; }
};
int main()
{
Foo foo{};
int i = foo.get<int, 4>();
double d = foo.get<double, 2>();
}
I have this simple code below, a template with 2 type parameters. If I declare my class with the same type (like BidirectionalMap<int,int>), I receive an error:
int BidirectionalMap<T,S>::operator [](T) const' : member function already defined or declared
Here's my template code:
template <class T, class S>
class BidirectionalMap{
int count(T t){
return 1;
}
int count(S s){
return 1;
}
};
The error you got is normal, because after substitution you have
template <>
class BidirectionalMap<int, int>
{
int count(int t){ return 1; }
int count(int s){ return 1; } // Duplicated method
};
To solve that, you may provide partial specialization:
template <class T>
class BidirectionalMap<T, T>
{
int count(T t) { return 1; }
};
In C++20, you might use requires to "discard" methods:
template <class T, class S>
class BidirectionalMap
{
int count(T t) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(S s) requires(!std::is_same<T, S>::value) { /*..*/ }
int count(T t) requires( std::is_same<T, S>::value) { /*..*/ }
};
I have the following code:
#include <string>
enum class Hobbit {
// typedef HobbitHelper helper;
UNKNOWN = -1, Bilbo, Frodo, Samwise
};
struct HobbitHelper {
static Hobbit decode(std::string const& s) {
if (s == "Bilbo") {
return Hobbit::Bilbo;
}
else if (s == "Frodo") {
return Hobbit::Frodo;
}
else if (s == "Samwise") {
return Hobbit::Samwise;
}
else {
return Hobbit::UNKNOWN;
}
}
};
enum class Wizard {
// typedef Apprentice helper;
UNKNOWN = -1, Gandalf, Radagast, Saruman
};
struct Apprentice { // WizardHelper :)
static Wizard decode(std::string const& s) {
if (s == "Gandalf") {
return Wizard::Gandalf;
}
else if (s == "Radagast") {
return Wizard::Radagast;
}
else if (s == "Saruman") {
return Wizard::Saruman;
}
else {
return Wizard::UNKNOWN;
}
}
};
template <typename T>
T
decoder(std::string s)
{
return ??::decode(s);
// if the typedefs were allowed, I could use T::helper::decode()
}
int main()
{
std::string s{ "Rincewind" };
auto h = decoder<Hobbit>(s);
auto w = decoder<Wizard>(s);
}
How can I arrange to call the appropriate helper class (HobbitHelper or Apprentice) in decoder? I can't declare a nested type inside the enum, as if it was a class. I also tried deriving the helper from the enum (since the helper itself has no data), but that isn't allowed either.
Any ideas?
You can just have the helper type trait be external and templated on the enum type, with an explicit specialization for each enum:
template <typename T> struct type_is { using type = T; };
template <typename > struct helper;
template <> struct helper<Hobbit> : type_is<HobbitHelper> { };
template <> struct helper<Wizard> : type_is<Apprentice> { };
template <typename T>
using helper_t = typename helper<T>::type;
And then decode would just access that:
template <typename T>
T decoder(std::string s)
{
return helper_t<T>::decode(s);
}
The simplest way to do it is to use ADL. You can use a type tag to make the compiler look in the appropriate namespace.
Consider:
template<typename T> struct adl_tag {};
namespace MiddleEarth {
enum class Hobbit {
// typedef HobbitHelper helper;
UNKNOWN = -1, Bilbo, Frodo, Samwise
};
Hobbit decode(std::string const& s, adl_tag<Hobbit>) {
if (s == "Bilbo") {
return Hobbit::Bilbo;
}
else if (s == "Frodo") {
return Hobbit::Frodo;
}
else if (s == "Samwise") {
return Hobbit::Samwise;
}
else {
return Hobbit::UNKNOWN;
}
}
}
template<typename T> T decode(std::string s) {
return decode(s, adl_tag<T>());
}
This is the solution employed by pretty much all C++ libraries- more or less. There's basically no additional effort involved. I didn't even have to mention Wizard.
My suggestion would be partial template specialization, although the answer from #Barry might be more like what you are looking for.
template <typename T>
T decoder(std::string s);
template<>
Hobbit decoder(std::string s)
{
return HobbitHelper::decode(s);
}
template<>
Wizard decoder(std::string s)
{
return Apprentice::decode(s);
}
Aside helper problem there is better solution than cascade if:
static Hobbit decode(std::string const& s) {
static std::unordered_map<std::strinng,Hobbit> choice {
{ "Bilbo", Hobbit::Bilbo },
{ "Frodo", Hobbit::Frodo },
{ "Samwise", Hobbit::Samwise }
};
auto f = choice.find( s );
return f != choice.end() ? f->second : Hobbit::UNKNOWN;
}
In the end I went with a slightly modified version of Barry's answer
template <typename T>
struct enumclass {
};
template<>
struct enumclass<Hobbit> {
using helper = HobbitHelper;
};
template<>
struct enumclass<Wizard> {
using helper = Apprentice;
};
because it lets me write the more mnemonic
template <typename T>
T
decoder(std::string s)
{
return enumclass<T>::helper::decode(s);
}
All the specializations can be distributed (i.e. enumclass <Hobbit> is in hobbit.h; enumclass<Wizard> is in wizard.h). All these headers must include a small header with the unspecialized template.
I have a template class. The class has a private member variable which I like to have preset to a certain value which differs for each template type.
I was thinking about different constructors for different types, but since the constructor has no parameters I have no idea how to do it.
Is it possible anyway ?
Thanks,
Use a traits template and specialize it with the value. something like:
template <typename T, typename Traits = MyTraits<T> >
class MyClass {
public:
int Foo ()
{
return Traits::Value;
}
};
template <>
class MyTraits<SomeClass>
{
public:
static int Value = 1;
};
template <>
class MyTraits<AnotherClass>
{
public:
static int Value = 2;
};
You can do it with a specialization on the type, the easiest form is:
#include <iostream>
template <typename T>
struct make {
static int value() {
return -1; // default
}
};
template <>
struct make<int> {
static int value() {
return 1;
}
};
template <>
struct make<double> {
static int value() {
return 2;
}
};
template <typename T>
struct foo {
const int val;
foo() : val(make<T>::value()) {}
};
int main() {
std::cout << foo<int>().val << ", " << foo<double>().val << "\n";
}
But you could also arrange it as an overload:
#include <iostream>
int value(void *) {
return -1; // default
}
int value(double *) {
return 2;
}
int value (int *) {
return 1;
}
template <typename T>
struct foo {
const int val;
foo() : val(value(static_cast<T*>(nullptr))) {}
};
int main() {
std::cout << foo<int>().val << ", " << foo<double>().val << "\n";
}
You could put the mapping from template parameters to values into a helper class, giving you something like this:
template<typename T> struct foo_helper;
template<> struct foo_helper<int> { static int getValue() {return 1; } };
template<> struct foo_helper<float> { static int getValue() {return 2; } };
....
template<typename T> class foo
{
int m;
foo():m(foo_helper<T>::getValue()){}
};