I have a struct which takes enum class value on the template parameter.
template <typename EnumValue>
struct Type
{
public:
static constexpr int VALUE = static_cast<int>(EnumValue);
};
enum class MyEnum {Val1, Val2};
std::cout << Type<MyEnum::Val2>::VALUE << std::endl;
I expected it to work, but it gives errors:
error: expected primary-expression before ‘)’ token
static constexpr int VALUE = static_cast<int>(EnumValue);
error: type/value mismatch at argument 1 in template parameter list for ‘template<class EnumValue> struct Type’
std::cout << Type<MyEnum::Val2>::VALUE << std::endl;
How to fix these errors without changing the template parameters for Type?
Since I don't want the template inputs to be changed,
I don't want to use something like this:
template <typename EnumType, EnumType EnumValue>
struct Type...
You can't.
typename EnumValue declares a type, it is not a value. You can't have Type<MyEnum::Val2> with an enum class in C++11.
In C++17 you will be able to write template <auto EnumValue> which does what you want.
As #Caleth has mentioned, you need to specify the enum type and enum value to the Type struct. But as far as you do not want to change the template parameters, why not going for an static method inside Type?
template <typename EnumType>
struct Type
{
public:
static constexpr int getValue(EnumType value)
{
return static_cast<int>(value);
}
};
enum class MyEnum { Val1, Val2 };
int main()
{
std::cout << Type<MyEnum>::getValue(MyEnum::Val2) << std::endl;
}
Related
I have seen an idiom for using Derived type traits in the base class of a CRTP pattern that looks like this:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
template <typename T>
struct Derived1 : Base<Derived1<T>>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <typename T>
struct traits<Derived1<T>> {
using size_type = size_t;
};
int main()
{
using T = float;
Derived1<T> d1;
d1.print();
}
My understanding is that the purpose of the idiom is to delay the instantiation of the Base class's size_type. What I am confused by is the fact that this pattern only seems to work if the derived class is itself templated. For instance, if we change the code to:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
struct Derived1 : Base<Derived1>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <>
struct traits<Derived1> {
using size_type = size_t;
};
int main()
{
Derived1 d1;
d1.print();
}
then we get the error
prog.cc: In instantiation of 'struct Base<Derived1>':
prog.cc:21:19: required from here
prog.cc:18:58: error: invalid use of incomplete type 'struct traits<Derived1>'
using size_type = typename traits<Derived>::size_type;
^
prog.cc:14:8: note: declaration of 'struct traits<Derived1>'
struct traits;
^~~~~~
prog.cc: In function 'int main()':
prog.cc:33:9: error: 'Derived1' is not a template
Derived1<float> d1;
Could somebody give me an explanation indicating why the templated derived class compiles, but the untemplated class does not?
The issue you're seeing has nothing to do with CRTP.
Here's what the standard mentions.
If a class template has been declared, but not defined, at the point of instantiation (13.7.4.1),
the instantiation yields an incomplete class type (6.7). [Example:
template<class T> class X; X<char> ch; // error: incomplete type
X<char>
Your traits has only been declared at the point of instantiation of Base<Derived>, hence as per the standard(see above extraction from the standard), struct traits<Derived> yields an incomplete type.
You should reorder the code so that it sees the traits<Derived> specialization when Base<Derived> gets instantiated.
The compilation error you are seeing has nothing to do with CRTP, it's just a bit of a mish-mash of dependencies.
In the code without the templation, your "Base" struct needs the definition of the specialized "traits" struct but it only appears afterwards, so it tries to use the incomplete type it saw in the declaration above.
To get the code to work you need to have the "traits" specialization before the Base declaration, which requires you to also add a declaration of Derived 1, here is a compiling code:
class Derived1;
template<typename Derived>
struct traits;
template <>
struct traits<Derived1> {
using size_type = size_t;
};
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
struct Derived1 : Base<Derived1>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
int main()
{
Derived1 d1;
d1.print();
}
Unlike the class template arguments, which have to be specified by the user of the template, the function template arguments are deduced by the compiler. Therefore, a natural question arises: why might one want to specify default function template arguments?
One usage I can come up with is when we want to force some of the function template arguments without needing to specify all of them. However, this seems to be a corner case. Are there other cases?
This might be a partial answer. One use I thought of is when we have a template parameter that does not appear as type in the function's parameter list and thus cannot be deduced. Providing a default argument for that template parameter might be very reasonable. The above comment by n.m. provides a good example of this usage.
Try to convert below func into the constructor( they dont have return type).
template<class T>
typename std::enable_if< std::is_fundamental<T>::value >::type func(T p_arg){}
template<class T>
typename std::enable_if< !std::is_fundamental<T>::value >::type func(T const &p_arg){}
Its pretty easy with default function template arguments.
Example:
template <typename Y, typename Y, int Z>
class Do{};
X,Y,Z are template parameters.
A user can use this like:
Do<int,int,1> doit;
While using a class template there is no way that template parameters get deduced from a function argument.
You call something "default" arguments...
template <typename Y, typename Y, int Z=9>
class Do{};
Here Z is defaulted to 9 if nothing was given from the using code like:
Do<int,int> doit;
And if your template arguments can be deduced from function arguments a user maybe want a special template instance to be used like:
template <typename T>
void func( const T&);
template<>
void func( const int& )
{
std::cout << "int in use" << std::endl;
}
template<>
void func( const double&)
{
std::cout << "double in use" << std::endl;
}
int main()
{
func(3.4); // calls double
func<int>(3.4); //calls int
}
I want to try to do a generic getter by using C++11, but I have an issue if I try to define the generic getter outside the template class.
This code works fine
template <typename T>
class test
{
public:
........
//generic getter
template <typename F>
auto getter_elem_member(F fun)->decltype(fun())
{ return elem.fun(); }
private
T elem;
};
but if I try the code in this way:
template <typename T>
class test
{
public:
........
//generic getter
template <typename F>
auto getter_elem_member(F fun)->decltype(fun());
private
T elem;
};
template <typename T>
template <typename F>
auto test<T>::getter_elem_member(F fun)->decltype(fun())
{ return elem.fun(); }
I obtain the error "Member declaration not found".
Where am I wrong?
Thanks in advance for any suggestions
I am doing exercises with new features, here a example that works (unless a warning)
#include <iostream>
#include <string>
template <typename T>
class test
{
public:
//costruttori - distruttori
test(){}
~test(){}
public:
//generic getter
template <typename F>
auto getter_elem_member(F fun)
{ return (elem.*fun)(); }
//generic getter
template <typename F>
auto getter_elem_member2(F fun)->decltype(fun())
{ return fun(); }
private:
T elem;
};
struct A
{
std::string print(){return "ciao";}
static std::string print2(){return "ciao";}
};
int main()
{
test<A> test1;
std::cout << test1.getter_elem_member(&A::print) << std::endl;
std::cout << test1.getter_elem_member2(A::print2) << std::endl;
}
If you're trying to make a proxy function which calls a member function of a private member variable through a member function pointer, I don't think you need decltype at all.
// Member function pointer version
template <class Ret>
Ret getter_elem_member(Ret (T::*fun)())
{ return (elem.*fun)(); }
// Generic function object version
template <class F>
auto getter_elem_member(F fun) -> decltype(fun())
{ return fun(); }
If a function pointer is given, the first one will be called. For other callable types, the second one will be called.
The second one, which is for a generic callable object, seems unnecessary. Since you can't access the private member in fun anyway, so it's better calling fun() outside than passing it and making your class call it.
It appears that you're trying to use a template function-like paradigm.
You should use std::function to do this. If not, you can probably get along with some sort of templated function pointer to do this.
Suppose you want to avoid narrowing when calling a function
void foo(char c) { /* ... */ }
foo(4); // get a compilation error here
You can define your target function, and a forwarding template overload that will attempt a non-narrowing conversion to the target type (DEMO):
void foo(char) {}
template <typename T>
void foo(T&& t) { foo(char{std::forward<T>(t)}); }
foo('a');
// foo(4); // ill-formed
foo({4});
// foo(0); // ill-formed
foo({0});
// foo(u'a'); // ill-formed
foo({u'a'});
int i = 2;
// foo(i); // ill-formed
// foo({i}); // ill-formed
This has the nice advantage that clients can force the conversion themselves by passing a braced-init-list. Since the braced-init-list impedes template deduction, only the target function can be selected by overload resolution. So even though e.g. foo(4) matches the template overload and is ill-formed - since int cannot in general be converted to char without narrowing - foo({4}) is well-formed since 4 can be converted to char without narrowing.
You can use a class template on T that has
1) a template constructor on a different type X that tries to instantiate the class when the parameter is not T
2) a constructor with T as param that takes care of the case where you are instantiating the class with the exact type
#include <iostream>
// g++-4.9 -Werror=narrowing -std=c++11 main2.cc
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55783
template <typename T>
struct no_narrowing
{
using type = T;
// this template constructor lets you try to
// instantiate a no_narrowing using a different
// type. if Narrowing would take place
// value{ val } takes care of it
template <typename X>
no_narrowing(X val) : value{val} {}
// if type is exactly T we use this
no_narrowing(type val) : value{val} {}
operator type() const { return value;}
type value;
};
template <typename T>
using nn = no_narrowing<T>;
void print(nn<char> v)
{
std::cout << v << std::endl;
}
int main(int argc, char *argv[])
{
int i = 2;
print('d');
print(i); // this will not compile
return 0;
}
Based on the answer in Detecting constexpr with SFINAE I'm trying to use SFINAE to check if a 'constexpr' is present in my class.
The problem is that the constexpr is a function pointer:
#include <type_traits>
#include <iostream>
typedef int (*ptr_t)();
int bar() { return 9; }
struct Foo {
static constexpr ptr_t ptr = &bar;
};
namespace detail {
template <ptr_t>
struct sfinae_true : std::true_type {};
template <class T>
sfinae_true<T::ptr> check(int);
// Commented out to see why clang was not evaluating to true. This should only be
// a comment when debugging!
// template <class>
// std::false_type check(...);
} // detail::
template <class T>
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
int main(int argc, char *argv[]) {
std::cout << has_constexpr_f<Foo>::value << std::endl;
return 0;
}
It seems to work fine using gcc, but clang complains:
test.cxx:23:39: error: no matching function for call to 'check'
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
^~~~~~~~~~~~~~~~
test.cxx:26:22: note: in instantiation of template class 'has_constexpr_f<Foo>' requested here
std::cout << has_constexpr_f<Foo>::value << std::endl;
^
test.cxx:16:25: note: candidate template ignored: substitution failure [with T = Foo]: non-type template argument for template parameter of pointer type 'ptr_t' (aka 'int (*)()') must have its address taken
sfinae_true<T::ptr> check(int);
~ ^
1 error generated.
Q1: Can anyone suggest a way of doing this which works both for Clang and GCC?
Q2: Is this a bug in gcc, clang or is this left undefined in the c++ standard?
That's not a bug in clang, but an unfortunate restriction of arguments for non-type template parameters of pointer type (see pointer as non-type template argument). Essentially, you can only use arguments of the form &something: [temp.arg.nontype]/1 (from n3797)
[if the template-parameter is a pointer, its argument can be] a constant expression (5.19) that designates the address of a
complete object with static storage duration and external or
internal linkage or a function with external or internal linkage,
including function templates and function template-ids but excluding
non-static class members, expressed (ignoring parentheses) as &
id-expression, where the id-expression is the name of an object or
function, except that the & may be omitted if the name refers to a
function or array and shall be omitted if the corresponding
template-parameter is a reference; or [..]
[emphasis mine]
You can however, use a function pointer in a constant expression that has a non-pointer type, for example a boolean expression such as
T::ptr != nullptr
This works under clang++3.5 and g++4.8.2:
#include <type_traits>
#include <iostream>
typedef int (*ptr_t)();
int bar() { return 9; }
struct Foo0 {
static constexpr ptr_t ptr = &bar;
};
struct Foo1 {
static const ptr_t ptr;
};
ptr_t const Foo1::ptr = &bar;
struct Foo2 {
static const ptr_t ptr;
};
//ptr_t const Foo2::ptr = nullptr;
namespace detail
{
template <bool>
struct sfinae_true : std::true_type {};
template <class T>
sfinae_true<(T::ptr != nullptr)> check(int);
// the result of the comparison does not care
template <class>
std::false_type check(...);
} // detail::
template <class T>
struct has_constexpr_f : decltype(detail::check<T>(0)) {};
int main(int argc, char *argv[]) {
std::cout << std::boolalpha << has_constexpr_f<Foo0>::value << std::endl;
std::cout << std::boolalpha << has_constexpr_f<Foo1>::value << std::endl;
std::cout << std::boolalpha << has_constexpr_f<Foo2>::value << std::endl;
return 0;
}
Note there's a difference between clang++ and g++ for the second output (Foo1): g++ says true, clang++ says false.