Let's suppose we have this class:
class MyEnumClass
{
public:
enum Type
{
Example0,
Count
};
using EnumType = Type;
};
And this one.
class MyEnumClass2
{
public:
enum Type2
{
Example0,
Count
};
};
And we want to handle something related to it in a different class. But this class also supports other different than MyEnumClass classes, MyEnumClass2 is included too and have not same members. The classes are not meant to be touched at all. So I want it to be copy constructible from its instantiable classes:
template<typename T, typename U>
class EnumClassHandler
{
public:
EnumClassHandler() : value(0) {}
// Here want to make an optional copy constructor
EnumClassHandler(const T::EnumType& value)
{
// Do whatever
}
// This class should also be supported
EnumClassHandler(const T::Type2& value)
{
//Do whatever
}
U value;
};
I would like this EnumClassHandler to support this:
typedef EnumClassHandler<MyEnumClass, uint32_t> MyEnumClassHandler;
typedef EnumClassHandler<MyEnumClass2, uint32_t> MyEnumClass2Handler;
int main()
{
MyEnumClassHandler example = MyEnumClass::Example0;
MyEnumClass2Handler example2 = MyEnumClass2::Example0;
}
Here is the wandbox code reflecting the problem, which is that fails on instantiating non supported constructors for different classes.
How can I make EnumClassHandler support optionally copy constructible for those, and a bunch of similar to MyEnumClass and MyEnumClass2 classes(so modifying those internally is not allowed), in c++14?
To enable the constructor only for the respective T::EnumType or T::Type2 you can do this:
template<typename T, typename U>
class EnumClassHandler
{
public:
EnumClassHandler() : value(0) {}
// only viable when T has T::EnumType
template <typename W = T>
EnumClassHandler(const typename W::EnumType& value)
{
//Do whatever
}
// only viable when T has T::Type2
template <typename W = T>
EnumClassHandler(const typename W::Type2& value)
{
//Do whatever
}
U value;
};
This will make your code work, while this
MyEnumClass2Handler example3 = MyEnumClass::Example0;
results in error:
<source>:56:47: error: conversion from 'MyEnumClass::Type' to non-scalar type 'MyEnumClass2Handler' {aka 'EnumClassHandler<MyEnumClass2, unsigned int>'} requested
56 | MyEnumClass2Handler example3 = MyEnumClass::Example0;
| ~~~~~~~~~~~~~^~~~~~~~
Live Demo.
PS: If possible I would rather add an EnumType alias to each MyEnumClassX to keep that complexity out of the EnumClassHandler. If this isnt feasible, I would use a type trait:
template <typename MYENUMCLASS>
struct enum_type_from_myenumclass {
using type = typename MYENUMCLASS::EnumType;
};
You can specialize it for each MyEnumClass that does not have the EnumType member alias:
template <>
struct enum_type_from_myenumclass<MyEnumClass2> {
using type = typename MyEnumClass2::Type2;
};
// ... and similar for others ...
Then the EnumClassHandler only needs to use enum_type_from_myenumclass<T>::type and doesn't need to care about the differently named aliases.
Live Demo
Related
I have created an options struct, intended to be used via designated initializer:
struct FooOptions {
bool enableReticulation;
};
void Foo(FooOptions&& opts);
Foo(FooOptions{.enableReticulation = true});
Unfortunately, because bool has a default constructor, it's also valid to do this:
Foo(FooOptions{});
but I don't want this; I want users of Foo to explicitly decide to enable reticulation or not. I can achieve this with a runtime error this way:
struct FooOptions {
bool enableReticulation = []() -> bool {
assert(false, "No value provided for enableReticulation");
}();
};
But I would prefer to do this with a compile time error. Is there any way to do that? I am OK with changing bool to SomeWrapper<bool> if necessary, as long I can mostly initialize SomeWrapper<T> as if it were T, but without a default initializer.
You clarified that this is about arbitrary classes, and not primitive types. For arbitrary classes, with arbitrary constructors: just delete the constructor, but explicitly delete the default constructor:
template<typename T> class SomeWrapper : public T {
SomeWrapper()=delete;
using T::T;
};
Then:
#include <vector>
foo F{ {1,2} }; // Works, initializes the vector with {1,2}
foo G{}; // Fails
This may not work like you want for primitive types. Just specialize SomeWrapper as needed. There aren't that many primitive types to deal with.
Way to handle classes and non-classes types, thank to SFINAE:
template<typename T, typename Enabler = void> class TWrapper;
template<typename T>
class TWrapper<T, std::enable_if_t<std::is_class<T>::value>> : public T {
public:
TWrapper()=delete;
using T::T;
};
template<typename T>
class TWrapper<T, std::enable_if_t<!std::is_class<T>::value>>
{
public:
TWrapper()=delete;
T value;
TWrapper(T arg) : value(arg) {}
operator T() const { return value; }
};
Demo
I've been experimenting with the Curiously Recurring Template Pattern for a generic single-argument functor and have two implementations: one using a template template parameter which works and a second where I try to access the derived Functor::type in the interface class. In the latter example, the compiler (gcc 5.4.0) reports
error: no type named 'type' in 'struct Cube< double >'
template<class T, template<class> class Functor>
class FunctorInterface_1 {
private:
const Functor<T> &f_cref;
public:
FunctorInterface_1() : f_cref(static_cast<const Functor<T>&>(*this)) {}
T operator() ( T val ) const { return f_cref(val); }
}; // FunctorInterface_1 (works)
template<class Functor>
class FunctorInterface_2 {
private:
const Functor &f_cref;
public:
using Ftype = typename Functor::type;
FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {}
Ftype operator() ( Ftype val ) const { return f_cref(val); }
}; // FunctorInterface_2 (no type in Functor!)
I then try to compile with T=double in main() of the following two classes:
template<class T>
struct Square : public FunctorInterface_1<T,Square> {
T operator()( T val ) const { return val*val; }
}; // Square
template<class T>
struct Cube : public FunctorInterface_2<Cube<T>> {
using type = T;
T operator() ( T val ) const { return val*val*val; }
}; // Cube
Can the FunctorInterface_2/Cube example be modified to work, or
is it necessary for the interface class to be templated on T as
in the first example? Thanks!
EDIT: Using gcc -std=c++14, I can get the second example to compile and run
by using auto return and argument types in FunctorInterface_1::operator(), however, as I understand, auto argument types are not part of the C++14 standard.
EDIT 2: Well I feel a bit thick. I just realized that I could template FunctorInterface_1::operator() on a new parameter, however, for the application I have in mind, I would really like my base class to be able to access types defined in the derived class.
When the line
using Ftype = typename Functor::type;
is processed in the base class, the definition of Functor is not available. Hence, you can't use Functor::type.
One way to get around this limitation is to define a traits class.
// Declare a traits class.
template <typename T> struct FunctorTraits;
template<class Functor>
class FunctorInterface_2 {
private:
const Functor &f_cref;
public:
// Use the traits class to define Ftype
using Ftype = typename FunctorTraits<Functor>::type;
FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {}
Ftype operator() ( Ftype val ) const { return f_cref(val); }
}; // FunctorInterface_2 (no type in Functor!)
// Forward declare Cube to specialize FunctorTraits
template<class T> struct Cube;
// Specialize FunctorTraits for Cube
template <typename T> struct FunctorTraits<Cube<T>>
{
using type = T;
};
template<class T>
struct Cube : public FunctorInterface_2<Cube<T>> {
using type = T;
T operator() ( T val ) const { return val*val*val; }
}; // Cube
Working code: https://ideone.com/C1L4YW
Your code could be simplified to
template<typename TDerived> class
Base
{
using Ftype = typename TDerived::type;
};
template<typename T> class
Derived: public Base<Derived<T>>
{
using type = T;
};
Derived<int> wat;
It does not work because at the point of Base instantiation Derived class is not complete, and compiler is not aware of Derived::type existence yet.
You have to understand that when you instantiate Cube<T> FunctionInterface_2<Cube<T>> gets instantiated first. This means that Cube<T> is an incomplete type while this is happening.
So when the compiler gets to the line using Ftype = typename Functor::type; Functor is incomplete and you cannot access any of its nested types.
In your case you can change FunctionInterface_2 to:
template<class Functor>
class FunctorInterface_2 {
private:
const Functor &f_cref;
public:
FunctorInterface_2() : f_cref(static_cast<const Functor&>(*this)) {}
template <class TT>
auto operator() ( TT && val ) -> decltype(f_cref(val)) const { return f_cref(val); }
};
So now accessing information about Functor is delayed until you call the operator() from FunctionInterface_2 at which point FunctionInterface_2 and Cube are fully instantiated.
Note: This question has already been answered by #r-sahu, but I'd like to elaborate on this and address clang's output specifically.
The problem can be demonstrated on a much smaller code sample: (#vtt suggested something similar)
template <typename _CRTP>
struct A {
using _C = typename _CRTP::C;
};
struct B : public A<B> {
using C = int;
};
Compiling that with clang will result in completely misleading error message: (godbolt)
<source>:3:32: error: no type named 'C' in 'B'
using _C = typename _CRTP::C;
~~~~~~~~~~~~~~~~^
<source>:6:19: note: in instantiation of template class 'A<B>' requested here
struct B : public A<B> {
^
1 error generated.
GCC's error message is a little more helpful: (godbolt)
<source>: In instantiation of 'struct A<B>':
<source>:6:19: required from here
<source>:3:33: error: invalid use of incomplete type 'struct B'
3 | using _C = typename _CRTP::C;
| ^
<source>:6:8: note: forward declaration of 'struct B'
6 | struct B : public A<B> {
| ^
As suggested in the accepted answer, implementing a trait type fixes the issue:
// this declaration must appear before the definition of A
template <typename _A>
struct a_traits;
template <typename _CRTP>
struct A {
// `a_traits<_CRTP>::type` is an incomplete type at this point,
// but that doesn't matter since `A` is also incomplete
using _C = typename a_traits<_CRTP>::type;
};
// this specialization must appear before the definition of B
template <>
struct a_traits<struct B> { // adding the type specifier `struct` will declare B
using type = int;
};
// specifying the template parameter will complete the type `A<B>`, which works since
// `a_traits<B>` is already complete at this point
struct B : public A<B> {
using C = int;
};
Is it possible to make a certain template function have 2 accessibility level for some certain template parameter? (via splitting into 2 functions?)
class B{
enum ENU{
T0,T1,T2
}
template<ENU T=T0> someType f(){ ... } //want T1,T2 = public, T0 = private
};
Current usage (the solution should not change it):-
B b;
int aa=b.f<T0>(); //should fail
std::string bb=b.f<T1>();// should ok
Edit: B has a lot of functions like this.
Here is the full code (just in case someone want to edit or use) https://ideone.com/ryNCml.
I doubt what you are trying to do is possible, as specializing functions on a value ain't allowed in C++.
Though if you don't need enumerations, you could write something similar:
class B {
public:
struct T0{};
struct T1{};
struct T2{};
template<typename T> void f(T, ...) {
static_assert(std::is_same_v<T, T1> || std::is_same_v<T, T2>);
}
private:
void f(T0, ...) {}
};
int main(int argc, char **argv) {
B b{};
b.f(T1{}); // Should compile
b.f(T0{}); // Should not compile
}
If you would use the same function implementation, you can either forward this to a common method, or simply put T0 private.
Alternatively, you could make use of a proxy object which could convert the value, though I'm not sure if this is standard C++ of an extension of the compiler I'm familiar with:
class B {
public:
enum class T { //< Strong typed!
T0,
T1,
T2
}
template <T t>
struct TWrapper {};
template <T ActualT>
void f(..., TWrapper<ActualT> tw = TWrapper<ActualT>{});
private:
template <>
struct TWrapper<T0> {};
}
As far as I can understand, you want to forbid the use of T0 as a template parameter while invoking member method f.
To do that, you can use either std::enable_if or a static_assert.
It follows a minimal, working example:
#include<type_traits>
class B {
public:
enum ENU { T0,T1,T2 };
template<ENU T>
std::enable_if_t<(T==T1||T==T2),int>
f() { return 42; }
template<ENU T>
int g(){
static_assert(T==T1||T==T2, "not allowed");
return 42;
}
};
int main() {
B b;
b.f<B::T1>();
// It doesn't work
//b.f<B::T0>();
b.g<B::T1>();
// It doesn't work
//b.g<B::T0>();
}
Given you want to support only a finite set of template arguments, I would write three functions which are not template functions, and give them the right visibility. Then make them delegate to a private template function which does the work. This would look like:
class B{
public:
enum ENU{
T0,T1,T2
}
private:
template<ENU T=T0> int f(){
std::cout<<"In enum "<<T<<std::endl;
return 0;
}
protected:
someType fT0() { return f<T0>(); }
public:
someType fT1() { return f<T1>(); }
someType fT2() { return f<T2>(); }
};
Contrary to your requirements, the usage changes - but this is often the simplest approach:
B b;
int aa=b.fT0(); // fails
int bb=b.fT1();// ok
Alternatively, you can make the template be public, but give it a dummy argument (with a default), and make the type of the dummy argument depend on the template parameter (via traits). If the type of the dummy is a private class, the template will only be callable by a member.
template <ENU T>
struct protection_traits;
class B{
friend class protection_traits<T0>; // So it has access to Protected.
protected:
struct Protected{};
public:
struct Public{};
enum ENU{
T0,T1,T2
}
template<ENU T=T0> int f( typename protection_traits<T>::type = {})
{ std::cout<<"In enum "<<T<<std::endl; }
};
template <ENU T>
struct protection_traits
{
typedef B::Public type; // Default to public
};
template<>
struct protection_traits<T0>
{
typedef B::Protected type; // But T0 uses Protected
};
Usage:
B b;
int aa=b.f<T0>(); // fails (no access to B::Protected)
int bb=b.f<T1>(); // ok
Note: This latter solution hasn't been fed to a compiler. There will be typos.
I have the following situation:
My problem revolves around using strongly typed enum classes as flags (just as in C# with the Flags-Attribute). I know this is not the way enum classes were meant to be used in the first place, but that it not the point of this question.
I have defined several operators and functions to use on these enum classes, and a custom type trait to distinguish normal enums from Flag-enums. Here's an example:
// Default type_trait which disables the following operators
template <typename T> struct is_flags : std::false_type {};
// Example operator to use enum class as flags
template <typename T>
std::enable_if_t<std::is_enum<T>::value && is_flags<T>::value, T&>
operator|=(T &t1, const T t2)
{
return t1 = static_cast<T>(static_cast<std::underlying_type_t<T>>(t1) |
static_cast<std::underlying_type_t<T>>(t2));
};
Now if I define any enum class i can do the following:
enum class Foo { A = 1, B = 2 };
enum class Bar { A = 1, B = 2 };
// Declare "Bar" to be useable like Flags
template <> struct is_flags<Bar> : std::true_type {};
void test()
{
Foo f;
Bar b;
f |= Foo::A; // Doesn't compile, no operator |=
b |= Bar::A; // Compiles, type_trait enables the operator
}
The above code works fine and using a macro for the template specialization it almost looks like the very convenient C# Flags-Attribute.
However, when the enum class is not defined in namespace scope, I run into an issue:
struct X
{
enum class Bar { A = 1, B = 2 };
// Following line gives: C3412: Cannot specialize template in current scope
template <> struct is_flags<Bar> : std::true_type {};
}
The type trait cannot be specialized here. I would need to define the trait outside of X, which is possible, but separates the "Flag-Attribute" from the enum declaration. It would be so nice to use this in our code since flags are used all over the place but in a rather old-fashioned manner (int + #define). All solutions to this problem I have found so far focus on classes instead of enums, where the solution is much simpler, since I can define the trait as a member of the class itself. Enums, however, cannot inherit, contain typedefs or whatever might be needed to differentiate a certain enum class from another.
So is there any possibility to define some kind of trait in a class-scope which can be used in global namespace scope to recognize special enum class-types?
EDIT: I should add that I'm using Visual Studio 2013.
UPDATE: Thanks for the answers, the tag-solution worked really well, although I had to make a subtle change (making it even more simple in the process). I'm now using this custom type trait:
template <typename T>
struct is_flags
{
private:
template <typename U> static std::true_type check(decltype(U::Flags)*);
template <typename> static std::false_type check(...);
typedef decltype(check<T>(0)) result;
public:
static const bool value = std::is_enum<T>::value && result::value;
};
Now, all I need to do is add Flags to the enum class, no matter what scope it's in:
enum class Foo { Flags, A = 0x0001, B = 0x0002 };
See also here for a similar problem and solution.
UPDATE 2: Since Visual Studio 2013 Update 2 this solution will cause compiler crashes when the is_flags trait is applied to ios-base headers. Therefore we are now using a different and cleaner approach, we use a template class which acts as the storage for an enum class and defines all operators on itself without any type-trait magic. The template class can be created implicit with the underlying enum class and explicit with the underlying type. Works a charm and is much less of an enable_if-mess.
You could tag the enumeration itself:
#include <type_traits>
template<typename T>
struct is_flags {
private:
typedef typename std::underlying_type<T>::type integral;
template<integral> struct Wrap {};
template<typename U>
static constexpr std::true_type check(Wrap<integral(U::EnumFlags)>*);
template<typename>
static constexpr std::false_type check(...);
typedef decltype(check<T>(0)) result;
public:
static constexpr bool value = std::is_enum<T>::value && result::value;
};
namespace Detail {
template <bool>
struct Evaluate;
template <>
struct Evaluate<true> {
template <typename T>
static T apply(T a, T b) { return T(); }
};
}
template <typename T>
T evalueate(T a, T b)
{
return Detail::Evaluate<is_flags<T>::value>::apply(a, b);
}
enum class E{ A = 1, B, C };
struct X {
enum class F{ EnumFlags, A = 1, B, C };
};
int main ()
{
// error: incomplete type ‘Detail::Evaluate<false>’ used in nested name specifier
// evalueate(E::A, E::B);
evalueate(X::F::A, X::F::B);
}
Here's an ugly solution using ADL instead of traits (of course you can hide the ADL inside the trait):
New operator template:
struct my_unique_enum_flag_type;
// Example operator to use enum class as flags
template <typename T>
enable_if_t<std::is_enum<T>::value
&& std::is_same<decltype(is_flags(std::declval<T>())),
my_unique_enum_flag_type>::value, T&>
operator|=(T &t1, const T t2)
{
return t1 = static_cast<T>(static_cast<underlying_type_t<T>>(t1) |
static_cast<underlying_type_t<T>>(t2));
};
Definition of is_flags for Bar:
struct X
{
enum class Bar { A = 1, B = 2 };
friend my_unique_enum_flag_type is_flags(Bar);
};
int main()
{
X::Bar a = X::Bar::A;
a |= X::Bar::B;
}
(preferably, use a more unique name than is_flags for ADL)
Inspired of boost::operators I thought the Barton-Nackman idiom could be used to implement from trival member methods.
Following is what I have tried (does not compile)
template<typename T>
class impl_get_set {
typename T::storage_type get() const {
return static_cast<const T *>(this)->data_;
}
void set(typename T::storage_type d) {
*static_cast<T *>(this)->data_ = d;
}
};
struct A : public impl_get_set<A> {
typedef int storage_type;
storage_type data_;
};
struct B : public impl_get_set<B> {
typedef double storage_type;
storage_type data_;
};
As this does not compile there is clearly something I have got wrong. My question is, can this be done, and if so how?
When using CRTP, you have to take care when designing the base, i.e. impl_get_set in this case. When the derived class instantiates the base specialization, e.g. as done with A: public impl_get_set<A>, the A class is still incomplete.
However the definition of impl_get_set uses typename T::storage_type in a member function declaration. This use requires a complete T. The C++03 way to solve that is to make any associated type that the CRTP base may need part of the class template parameters:
template<typename Derived, typename StorageType>
struct get_set {
typedef StorageType storage_type;
// It's possible to define those inline as before where
// Derived will be complete in the body -- which is why
// CRTP is possible at all in the first place
storage_type get() const;
void set(storage_type s);
// Convenience for clients:
protected:
typedef get_set get_set_base;
};
struct A: get_set<A, int> {
// Member type is inherited
storage_type data;
};
template<typename T>
struct B: get_set<B<T>, double> {
// Incorrect, storage_type is dependent
// storage_type data;
// First possibility, storage_type is
// still inherited although dependent
// typename B::storage_type data;
// Second possibility, convenient if
// storage_type is used multiple times
using typename B::get_set_base::storage_type;
storage_type data;
void foo(storage_type s);
};
boost::iterator_facade is a good example of a well-written C++03-style CRTP wrapper from Boost.Iterator.
C++11 gives another way to write a CRTP base thanks in part to default template arguments for function templates. By making the derived class parameter dependent again, we can use it as if it were complete -- it will only be examined when the member function template of the CRTP base specialization is instantiated, once it is complete, and not when the CRTP base specialization itself is:
// Identity metafunction that accepts any dummy additional
// parameters
template<typename T, typename... Dependent>
struct depend_on { using type = T; };
// DependOn<T, D> is the same as using T directly, except that
// it possibly is dependent on D
template<typename t, typename... D>
using DependOn = typename depend_on<T, D...>::type;
template<typename Derived>
struct get_set {
template<
// Dummy parameter to force dependent type
typename D = void
, typename Storage = typename DependOn<Derived, D>::storage_type
>
Storage get() const
{
// Nothing to change, Derived still complete here
}
};
In fact, for your example get_set arguably doesn't need to care about whether a member type is present or not:
// std::declval is from <utility>
template<
typename D = void
, typename Self = DependOn<Derived, D>
>
auto get() const
-> decltype( std::declval<Self const&>().data )
{ return static_cast<Derived const&>(*this).data; }
This implementation of get has subtly different semantics from your own in that it returns a reference to data but that's on purpose.
The best I could figure out is that you're in a chicken/egg problem.
struct A uses impl_get_set as base, that forces instantiation. But at that point A is incomplete, its contents not yet available. Therefore T::storage_type fails to resolve to anything.
The only workaround I found was to just have another template param for impl_get_set and pass it from above. So go the opposite direction:
template<typename T, typename ST>
class impl_get_set {
public:
typedef ST storage_type;
storage_type get() const {
return static_cast<const T *>(this)->data_;
}
void set(storage_type d) {
*static_cast<T *>(this)->data_ = d;
}
};
struct A : public impl_get_set<A, int> {
storage_type data_;
};
(A is currently not used in the base, I left it in for possible other plans)