I would like to do something like this:
#include <iostream>
class a {
public:
a() : i(2) {}
template <typename ...ts>
void exec() {
f<ts...>();
std::cout << "a::()" << std::endl;
}
int i;
private:
template <typename t>
void f() {
i += t::i;
}
template <typename t, typename ...ts>
void f() {
f<t>();
f<t, ts...>();
}
};
struct b {
static const int i = -9;
};
struct c {
static const int i = 4;
};
int main()
{
a _a;
_a.exec<b,c>();
std::cout << _a.i << std::endl;
}
The idea is to get the same information from a group of classes, without the need of an object of each class.
Does anyone know if it is possible?
Thanks!
In case Your compiler does not support C++17:
template <typename ...ts>
void f() {
for ( const auto &j : { ts::i... } )
i += j;
}
In C++17, your class would simply be
class a {
public:
a() : i(2) {}
template <typename ...ts>
void exec() {
((i += ts::i), ...); // Folding expression // C++17
std::cout << "a::()" << std::endl;
}
int i;
};
Possible in C++11 too, but more verbose.
Reasons why your code is not compiling:
Syntax of specializing templates is a little different.
You need to put the most general case first.
You can't partially specialize functions, only classes.
Partial specialization is not allowed within classes, only in namespaces.
Here is an example for C++11.
#include <iostream>
template<typename t, typename ...ts>
class a {
public:
static constexpr int x = t::i + a<ts...>::x;
};
template<typename t>
class a<t> {
public:
static constexpr int x = 2 + t::i;
};
struct b {
static constexpr int i = -9;
};
struct c {
static constexpr int i = 4;
};
int main()
{
constexpr int result = a<b,c>::x;
std::cout << result << std::endl;
}
Remember that templates are calculated during compilation so, for optimization sake, it is a good idea to write them in a way that allows them to be constexpr.
Related
Please, before marking this as a duplicate of This question read the entirety of the post
This piece of code fails to compile, with a template deduction error:
#include <iostream>
#include <type_traits>
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
template<typename TYPE>
void Bar(MyType<TYPE> Input)
{
std::cout << typeid(Input).name() << std::endl;
}
};
int main()
{
MyClass<float, 1> c;
c.Foo();
return 0;
}
I understand the point that was made in the question i linked above, which is that "the condition which allows to choose the type to be deduced depends on the type itself", however, why would the compiler fail in the specific case i provided as the condition here seems to be fully independent from the type, or is there something i'm missing?
I would be more than happy if someone could refer to a section of the c++ standard that would allow me to fully understand this behaviour.
As the linked question, TYPE is non deducible. MyType<TYPE> is actually XXX<TYPE>::type.
You have several alternatives, from your code, I would say one of
Bar no longer template:
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
void Bar(MyType<T> Input)
{
std::cout << typeid(Input).name() << std::endl;
}
};
requires (or SFINAE/specialization for pre-c++20):
template<typename T = float, int N>
class MyClass
{
public:
template<typename DATA_TYPE>
using MyType = std::conditional_t<(N>0), DATA_TYPE, double>;
MyType<T> Var;
void Foo()
{
Bar(Var);
}
template<typename TYPE>
void Bar(TYPE Input) requires(N > 0)
{
std::cout << typeid(Input).name() << std::endl;
}
void Bar(double Input) requires(N <= 0)
{
std::cout << typeid(Input).name() << std::endl;
}
};
I believe this is fairly simply to achieve, but I can't figure out how.
Take the following example class:
class Example {
public:
template <typename T>
size_t foo(T& v) const;
};
How can I provide two implementations for this method depending on if T is a POD? I know there is an std::is_pod type trait, but I can't figure out how to have it enable the correct function.
I also need to be able to provide specific specializations for certain types of T regardless of if they are PODs or not. For example, I want to be able to write:
template <>
size_t foo<uint8_t>(uint8_t& b);
While all other types of T are chosen based upon being PODs or not.
EDIT
I have been looking at the information everyone has been giving and have come up with the following, however, this still does not work (throws a compiler error). I can't understand why.
class Example {
public:
template <typename T, bool U = std::is_trivially_copyable<T>::value>
size_t foo(T& v) const;
};
template <typename T>
size_t Example::foo<T, true>(T& v) const {
//Do something if T is mem copyable
}
template <typename T>
size_t Example::foo<T, false>(T& v) const {
//Do something if T is not mem copyable
}
Which results in "non-class, non-variable partial specialization 'foo<T, true>' is not allowed"
You can do it in the following way.
#include <iostream>
#include <type_traits>
struct A {
int m;
};
struct B {
int m1;
private:
int m2;
};
struct C {
virtual void foo() {};
};
// is_pod is deprecated since C++ 20
template <typename T>
std::enable_if_t<std::is_pod_v<T>, size_t> foo(const T& pod)
{
std::cout << &pod << " is_pod\n";
return 0;
}
template <>
size_t foo<uint8_t>(const uint8_t& b)
{
std::cout << int(b) << " is uint8_t\n";
return 1;
}
template <>
size_t foo<int>(const int& b)
{
std::cout << int(b) << " is int\n";
return 1;
}
int main()
{
uint8_t a = 2;
foo(a);
foo(22);
// will compile
A instance;
foo(instance);
// will not compile
B b;
//foo(b);
// will not compile
C c;
//foo(c);
}
output
2 is uint8_t
22 is int
010FFA64 is_pod
Here is what I did to get it to work correctly:
#include <type_traits>
#include <iostream>
class Example {
public:
Example(int a) : _a(a) {}
virtual void bar() {}
template <typename T, typename std::enable_if<std::is_trivially_copyable<T>::value, size_t>::type = 0>
size_t foo(T& v) const {
std::cout << "T is trivially copyable" << std::endl;
return sizeof(T);
}
template <typename T, typename std::enable_if<!std::is_trivially_copyable<T>::value, size_t>::type = 0>
size_t foo(T& v) const {
std::cout << "T is not trivially copyable" << std::endl;
return sizeof(T);
}
private:
int _a;
int _b;
int _c;
};
template <>
size_t Example::foo<unsigned int>(unsigned int& v) const {
std::cout << "T is unsigned int" << std::endl;
return sizeof(unsigned int);
}
int main() {
Example e(10);
int a;
e.foo(a);
char b;
e.foo(b);
e.foo(e);
unsigned int c;
e.foo(c);
return 0;
}
The output of which looks like:
T is trivially copyable
T is trivially copyable
T is not trivially copyable
T is unsigned int
This is based upon the following Provide/enable method to in a class based on the template type
I need to define a class, foo, with a static member variable template, foo::static_variable_template<T>. This member should only exist when T fulfills certain requirements. For example, when the constexpr static function T::constexpr_static_function() exists. Otherwise, foo::static_variable_template<T> should not exist. Moreover, I would like to be able to test for the existence of foo::static_variable_template<T> at compile-time via SFINAE.
Here is an approximation of what I would like to do:
#include <iostream>
struct foo
{
template<class T>
static constexpr int static_variable_template =
T::constexpr_static_function();
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U,
int = T::template static_variable_template<U>>
void test_for_static_variable_template(int)
{
std::cout << "yes it has\n";
}
template<class T, class U>
void test_for_static_variable_template(...)
{
std::cout << "no it hasn't\n";
}
int main()
{
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
This approximation nearly works, but only if foo::static_variable_template has a second, defaulted template parameter. Because this second parameter is an implementation detail, I'd like to hide it from the public interface of foo::static_variable_template.
Is this possible in C++17?
I am not sure if your intent is to initialise foo::static_variable_template with 0 if T::constexpr_static_function() is missing or you want to disable it entirely. In case of the former, this might be useful. For example, this (clunky) solution works (requires C++17 for if constexpr; note that your variable is now a function):
#include <iostream>
template <typename T>
class has_func
{
typedef char does;
typedef long doesnt;
template <typename C> static does test( decltype(&C::constexpr_static_function) );
template <typename C> static doesnt test(...);
public:
static constexpr bool value()
{
return sizeof(test<T>(0)) == sizeof(char);
}
};
struct foo
{
template<class T>
static constexpr int static_variable_template()
{
if constexpr (has_func<T>::value())
{
return T::constexpr_static_function();
}
return 0;
}
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U>
void test_for_static_variable_template(...)
{
if constexpr (has_func<U>::value())
{
std::cout << "yes it has\n";
}
else
{
std::cout << "no it hasn't\n";
}
}
int main()
{
std::cout << foo::static_variable_template<has_constexpr_static_function>() << "\n";
std::cout << foo::static_variable_template<hasnt_constexpr_static_function>() << "\n";
/// Original test
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
Prints
42
0
yes it has
no it hasn't
Tested with clang 5.0.1.
In case you want to disable foo::static_variable_template entirely, you might need to use std::enable_if:
#include <iostream>
template <typename T>
class has_func
{
typedef char does;
typedef long doesnt;
template <typename C> static does test( decltype(&C::constexpr_static_function) );
template <typename C> static doesnt test(...);
public:
static constexpr bool value()
{
return sizeof(test<T>(0)) == sizeof(char);
}
};
struct foo
{
template<class T, typename std::enable_if<has_func<T>::value()>::type ...>
static constexpr int static_variable_template()
{
if constexpr (has_func<T>::value())
{
return T::constexpr_static_function();
}
return 0;
}
// XXX this works but requires a second defaulted template parameter
// template<class T, int = T::constexpr_static_function()>
// static constexpr int static_variable_template =
// T::constexpr_static_function();
};
struct has_constexpr_static_function
{
static constexpr int constexpr_static_function() { return 42; }
};
struct hasnt_constexpr_static_function
{
};
template<class T, class U>
void test_for_static_variable_template(...)
{
if constexpr (has_func<U>::value())
{
std::cout << "yes it has\n";
}
else
{
std::cout << "no it hasn't\n";
}
}
int main()
{
std::cout << foo::static_variable_template<has_constexpr_static_function>() << "\n";
// We can't print this because it doesn't exist.
// std::cout << foo::static_variable_template<hasnt_constexpr_static_function>() << "\n";
/// Original test
test_for_static_variable_template<foo, has_constexpr_static_function>(0);
test_for_static_variable_template<foo, hasnt_constexpr_static_function>(0);
}
In this line of thought, I am not sure if you can disable a static template variable with std::enable_if. To quote the great Riemann, "I have for the time being, after some fleeting vain attempts, provisionally put aside the search for this..."
My real example is quite big, so I will use a simplified one. Suppose I have a data-type for a rectangle:
struct Rectangle {
int width;
int height;
int computeArea() {
return width * height;
}
}
And another type that consumes that type, for example:
struct TwoRectangles {
Rectangle a;
Rectangle b;
int computeArea() {
// Ignore case where they overlap for the sake of argument!
return a.computeArea() + b.computeArea();
}
};
Now, I don't want to put ownership constraints on users of TwoRectangles, so I would like to make it a template:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
// Ignore case where they overlap for the sake of argument!
return a.computeArea() + b.computeArea();
}
};
Usages:
TwoRectangles<Rectangle> x;
TwoRectangles<Rectangle*> y;
TwoRectangles<std::shared_ptr<Rectangle>> z;
// etc...
The problem is that if the caller wants to use pointers, the body of the function should be different:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
assert(a && b);
return a->computeArea() + b->computeArea();
}
};
What is the best way of unifying my templated function so that the maxiumum amount of code is reused for pointers, values and smart pointers?
One way of doing this, encapsulating everything within TwoRectangles, would be something like:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
return areaOf(a) + areaOf(b);
}
private:
template <class U>
auto areaOf(U& v) -> decltype(v->computeArea()) {
return v->computeArea();
}
template <class U>
auto areaOf(U& v) -> decltype(v.computeArea()) {
return v.computeArea();
}
};
It's unlikely you'll have a type for which both of those expressions are valid. But you can always add additional disambiguation with a second argument to areaOf().
Another way, would be to take advantage of the fact that there already is a way in the standard library of invoking a function on whatever: std::invoke(). You just need to know the underlying type:
template <class T, class = void>
struct element_type {
using type = T;
};
template <class T>
struct element_type<T, void_t<typename std::pointer_traits<T>::element_type>> {
using type = typename std::pointer_traits<T>::element_type;
};
template <class T>
using element_type_t = typename element_type<T>::type;
and
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
using U = element_type_t<T>;
return std::invoke(&U::computeArea, a) +
std::invoke(&U::computeArea, b);
}
};
I actually had a similar problem some time ago, eventually i opted not to do it for now (because it's a big change), but it spawned a solution that seems to be correct.
I thought about making a helper function to access underlying value if there is any indirection. In code it would look like this, also with an example similar to yours.
#include <iostream>
#include <string>
#include <memory>
namespace detail
{
//for some reason the call for int* is ambiguous in newer standard (C++14?) when the function takes no parameters. That's a dirty workaround but it works...
template <class T, class SFINAE = decltype(*std::declval<T>())>
constexpr bool is_indirection(bool)
{
return true;
}
template <class T>
constexpr bool is_indirection(...)
{
return false;
}
}
template <class T>
constexpr bool is_indirection()
{
return detail::is_indirection<T>(true);
}
template <class T, bool ind = is_indirection<T>()>
struct underlying_type
{
using type = T;
};
template <class T>
struct underlying_type<T, true>
{
using type = typename std::remove_reference<decltype(*(std::declval<T>()))>::type;
};
template <class T>
typename std::enable_if<is_indirection<T>(), typename std::add_lvalue_reference<typename underlying_type<T>::type>::type>::type underlying_value(T&& val)
{
return *std::forward<T>(val);
}
template <class T>
typename std::enable_if<!is_indirection<T>(), T&>::type underlying_value(T& val)
{
return val;
}
template <class T>
typename std::enable_if<!is_indirection<T>(), const T&>::type underlying_value(const T& val)
{
return val;
}
template <class T>
class Storage
{
public:
T val;
void print()
{
std::cout << underlying_value(val) << '\n';
}
};
template <class T>
class StringStorage
{
public:
T str;
void printSize()
{
std::cout << underlying_value(str).size() << '\n';
}
};
int main()
{
int* a = new int(213);
std::string str = "some string";
std::shared_ptr<std::string> strPtr = std::make_shared<std::string>(str);
Storage<int> sVal{ 1 };
Storage<int*> sPtr{ a };
Storage<std::string> sStrVal{ str };
Storage<std::shared_ptr<std::string>> sStrPtr{ strPtr };
StringStorage<std::string> ssStrVal{ str };
StringStorage<const std::shared_ptr<std::string>> ssStrPtr{ strPtr };
sVal.print();
sPtr.print();
sStrVal.print();
sStrPtr.print();
ssStrVal.printSize();
ssStrPtr.printSize();
std::cout << is_indirection<int*>() << '\n';
std::cout << is_indirection<int>() << '\n';
std::cout << is_indirection<std::shared_ptr<int>>() << '\n';
std::cout << is_indirection<std::string>() << '\n';
std::cout << is_indirection<std::unique_ptr<std::string>>() << '\n';
}
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()){}
};