I'm trying to run the following code using VS2013
#include<iostream>
enum class MyEnum : char {
one, two, three
};
struct MyStruct {
MyEnum me;
};
class MyClass{
MyStruct ms{ MyEnum::one };
};
int main() {
std::cout << "compiled";
}
but what I get is an
error C2664: 'MyStruct::MyStruct(const MyStruct &)' : cannot convert argument 1 from 'MyEnum'to 'const MyStruct &'
Compiling the same code on www.compileonline.com gives no errors. Am I missing something obvious here?
EDIT: I would also like to mention that the following code compiles without errors.
...
int main() {
MyStruct ms{ MyEnum::one };
std::cout << "compiled";
}
As n.m. said in a comment, it is likely that VS2013 is missing something.
As a temporary solution you could add a constructor to MyStruct that takes MyEnum as a parameter.
struct MyStruct {
MyEnum me;
MyStruct( MyEnum me ):
me( me )
{
}
};
Related
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;
}
My code needs to test various pixel types for "validity". For example, floating point pixels are invalid if they report true for std::isnan().
So I have a "validator" template struct that I specialize for my various pixel types (here, just for float). My code uses a global template function to invoke the right overload through SFINAE
// Dummy implementation breaks compilation if no overload found.
template<class PEL, typename Enable=void> struct pixel_validator { };
template<class PEL>
struct pixel_validator<PEL, typename std::enable_if<std::is_floating_point<PEL>::value>::type>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
template<class PEL>
inline bool is_valid_pixel(const PEL& p)
{
// Dispatch to validator above
return pixel_validator<PEL>::validate(p);
};
void main
{
float x = 1.0f;
std::cout << "is it valid ?" << std::boolalpha << is_valid_pixel(x);
}
And this example works just fine. The pixel_validator specialization for float is chosen. All is well.
But then I tried to reduce the verbosity of my template expressions for clarity via a custom version of "std::enable_if" specifically for float.
template<class T, class VAL=T>
struct enable_if_floating
: std::enable_if<std::is_floating_point<T>::value, VAL>
{};
So now instead of writing this:
std::enable_if<std::is_floating_point<PEL>::value>::type
I can write
enable_if_floating<PEL>::value
... so my validator becomes:
template<class PEL>
struct pixel_validator<PEL, typename enable_if_floating<PEL>::type>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
Unfortunately, the moment that I change my "pixel_validator" to use it, the code fails to build. My enable_if_floating does not work and so Visual Studio cannot find the appropriate specialization. My output is not surprising then.
1>------ Build started: Project: TestApp7, Configuration: Debug Win32 ------
1>TestApp7.cpp
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: 'validate': is not a member of 'pixel_validator<PEL,void>'
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: with
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: [
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(62,34): error C2039: ]
1>C:\Test\TestApp7\TestApp7.cpp(62): message : see declaration of 'pixel_validator<PEL,void>'
1>C:\Test\TestApp7\TestApp7.cpp(62): message : with
1>C:\Test\TestApp7\TestApp7.cpp(62): message : [
1>C:\Test\TestApp7\TestApp7.cpp(62): message : PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(62): message : ]
1>C:\Test\TestApp7\TestApp7.cpp(82): message : see reference to function template instantiation 'bool is_valid_pixel<float>(const PEL &)' being compiled
1>C:\Test\TestApp7\TestApp7.cpp(82): message : with
1>C:\Test\TestApp7\TestApp7.cpp(82): message : [
1>C:\Test\TestApp7\TestApp7.cpp(82): message : PEL=float
1>C:\Test\TestApp7\TestApp7.cpp(82): message : ]
1>C:\Test\TestApp7\TestApp7.cpp(62,1): error C3861: 'validate': identifier not found
1>Done building project "TestApp7.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
My question is, why? What is wrong with my enable_if_floating?
Note: I even put this code in my main(), just for sanity checking. If my template were bad, I would expect the static_assert() to fail, but it does not.
// Sanity check #2. Does my enable_if_floating test reports that float
// enables because it's numeric? If not then the static_assert below should fail
using float_type = enable_if_floating<float>::type;
static_assert(std::is_same_v<float_type, float>, "Not same as float...");
Note also: My real world code uses a predicate that saves a whole lot more space than in this simple example
Not sure is the only problem but is a problem.
If you write
template<class T, class VAL=T>
struct enable_if_floating
: std::enable_if<std::is_floating_point<T>::value, VAL>
{};
the default returned type is T where, for std::is_enable_if, is void.
So
template<class PEL>
struct pixel_validator<PEL, typename enable_if_floating<PEL>::type>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
become, when PEL is a floating point type,
template<class PEL> // .....VVV should be void, not PEL
struct pixel_validator<PEL, PEL>
{
static bool validate(const PEL& p) { return !std::isnan(p); }
};
that doesn't matches the pixel_validator declaration (and main definition)
template<class PEL, typename Enable=void>
struct pixel_validator
{ };
because the expected second type is void, not PEL.
I see two possible alternative solutions: or you use void as default value for enable_is_floating second template parameter
// ...........................VVVV
template<class T, class VAL = void>
struct enable_if_floating
: std::enable_if<std::is_floating_point<T>::value, VAL>
{ };
or you use PEL as default value for pixel_validator second template parameter
template <typename PEL, typename = PEL>
struct pixel_validator
{ };
I suggest the first one to homogeneity with std::enable_if and standard C++ library.
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();
}
I'd like to implement a class like the one below with a member function template that takes a callable type F and applies it to the instance.
This compiles and runs in Visual Studio 15 but fails in clang with the error
[x86-64 clang 4.0.0] error: invalid use of incomplete type 'Foo'
struct Foo
{
template<typename F>
auto applyFunctionToMe(F&& func)->decltype( func( Foo() ) )
{
return func( *this);
}
int contents;
};
int main()
{
Foo bar;
auto result = bar.applyFunctionToMe([](const Foo& f){ return f.contents;});
return result;
}
Is there a way to get this to work under Clang in C++11?
Which compiler is more correct according to standard?
Try decltype(func(*this)) instead of decltype( func( Foo() ) )
I'm not sure whether or not this is standards-compliant, but clang apparently doesn't like using the Foo() constructor within the definition of Foo.
the following code produces an internal compiler error (VS2015)
struct A
{
constexpr A(){}
constexpr int bar()
{
return 3;
}
};
struct B : A
{
constexpr B(){}
constexpr int foo()
{
return A::bar();
}
};
int main()
{
constexpr B b;
constexpr int dummy = b.foo();
return 1;
}
However, if i'd remove the A:: qualifier:
constexpr int foo()
{
return bar();
}
it will be compiled.
problem arises when these methods have the same name, and I need to invoke the base class method. (e.g. when using recursive template inheritence)
any workarounds?
The actual problem is b is declared as const (constexpr implies const on objects) and you are trying to call non-const (since C++14, constexpr doesn't imply const on methods, see here) method with the const object...
According to the standard, you should not be able to solve the problem by simply removing A:: nor by the static_cast the way you did. Pre-RTM version of Visual Studio 2015 allows you to do this only because its support for constexpr is preliminary and very buggy. C++11 constexpr (but unfortunately not C++14 extended constexpr) expected to be fully supported in the RTM version of VS 2015 (see here).
The correct version of your code is:
struct A
{
constexpr A(){}
constexpr int bar() const
{
return 3;
}
};
struct B : A
{
constexpr B(){}
constexpr int foo() const
{
return A::bar();
}
};
int main()
{
constexpr B b;
constexpr int dummy = b.foo();
return 1;
}
Found a solution.
"this" should be casted to const A*:
struct B : A
{
constexpr B(){}
constexpr int foo()
{
return static_cast<const A*>(this)->bar();
}
};
Also works when the methods have the same name.