I'm trying to compile a library which depends on boost-1_72 with visual studio 2019, but error occurs in vector.hpp file. the error is C2993 'J' is not a valid type for non-type template parameter 'J' at line 245, and another error is C4430 missing type specifier - int assumed.Note:C++ does not support default-int at line 252.
private:
template <std::size_t J>
using store_at = decltype(store_at_impl(static_cast<vector_data*>(nullptr)));
public:
template <typename J>
BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
typename store_at<J::value>::elem_type& at_impl(J)
{
return store_at<J::value>::elem;
}
template <typename J>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
typename store_at<J::value>::elem_type const& at_impl(J) const
{
return store_at<J::value>::elem;
}
};
} // namespace boost::fusion::vector_detail
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 want to disable copy constructor of some template class conditionally. In other words, I want disable copy constructor, if base type is not copy constructible. To solve such problem (in educational purposes) I decided to write following program. (Here is link to ideone https://ideone.com/QY0NHJ) Below is source of my program:
#include <algorithm>
#include <type_traits>
using namespace std;
template <typename Data>
class Container
{
public:
typedef Container<Data> self_type;
Container():
m_data()
{
}
Container(const typename
std::enable_if<std::is_copy_constructible<Data>::value,
self_type>::type& other_data) :
m_data(other_data.m_data)
{
}
Container(self_type&& other)
{
std::swap(m_data, other.m_data);
}
private:
Data m_data;
};
class SomeData
{
public:
SomeData(){}
SomeData(const SomeData&) = delete;
};
int main()
{
Container<SomeData> container;
return 0;
}
But message from compiler really confuses me:
prog.cpp: In instantiation of ‘class Container’:
prog.cpp:41:22: required from here
prog.cpp:17:2: error: no type named ‘type’ in ‘struct std::enable_if >’
Container(const typename std::enable_if::value
As I understand it should lead to SFINAE and nothing should be arised from compiler. Where am I wrong?
As I understand it should lead to SFINAE
SFINAE means "substitution failure is not an error". You need substitution to occur in order to SFINAE out something. In this case, it is sufficient to add a default template parameter to your copy constructor:
template <typename D = Data>
Container(const typename std::enable_if<std::is_copy_constructible<D>::value,
self_type>::type& other_data) :
m_data(other_data.m_data)
{
}
live example on wandbox
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 )
{
}
};
I'm trying to do the following (only relevant parts of code below):
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
static constexpr char* err_value = "Type is not a container model";
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
static_assert(false, IsContainerCheck<ResultType>::err_value)
return 0;
}
};
template<>
struct run<true_t> {
constexpr static int apply() {
return 0;
}
};
}
This fails because the static_assert allows only literals to be printed. The same is with BOOST_STATIC_ASSERT_MSG macro.
So my question is - is there any way to output a constexpr string during compilation?
If there is a gcc extension providing this functionality that would also be great.
Used compiler gcc 4.8.1
GCC does not provide such a mechanism as you want. However you will not need
it if you are able to refactor your code somewhat as illustrated in the
following program. (I have filled in a few gaps so as to give us a
compilable example):
#include <type_traits>
#include <vector>
template<typename ContainerType>
struct is_container
{
static bool const value = false;
};
template<>
struct is_container<std::vector<int>>
{
static bool const value = true;
};
template<typename ContainerType>
struct IsContainerCheck // : is_container<ContainerType> <- Uneccessary
{
static_assert(is_container<ContainerType>::value,
"Type is not a container model");
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
return (IsContainerCheck<ResultType>(),0);
}
};
// No such specialization is necessary. Delete it.
// template<>
// struct run<true_t> {
// constexpr static int apply() {
// return 0;
// }
//};
}
using namespace _check_concept;
int main(int argc, char **argv)
{
auto verdict0 = run<std::vector<int>>::apply();
(void)verdict0;
// The following line will static_assert: "Type is not a container model"
auto verdict1 = run<float>::apply();
(void)verdict1;
return 0;
}
In your specialization _check_concept::struct run<true_t> I presume that
true_t is not an alias or equivalent of std::true_type, but rather
just a place-holder for some ResultType that is a container type. As
the test program shows, no such specialization is now necessary, because
IsContainerCheck<ResultType>() will static_assert, or not, depending
on ResultType, in the unspecialized run<ResultType>::apply().
I had some time (and a good liqueur to come along with it) to think more about the problem. This is what I came up with:
namespace _details {
struct PassedCheck {
constexpr static int printError () {
return 0; //no error concept check passed
}
};
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept_impl;
template<template<typename> class ConceptCheck, typename FirstType, typename ...ModelTypes>
struct check_concept_impl<ConceptCheck, FirstType, ModelTypes...> : mpl::eval_if< typename ConceptCheck<FirstType>::type,
check_concept_impl<ConceptCheck, ModelTypes...>,
mpl::identity<ConceptCheck<FirstType>>>
{ };
template<template<typename> class ConceptCheck, typename LastType>
struct check_concept_impl<ConceptCheck, LastType> : mpl::eval_if<typename ConceptCheck<LastType>::type,
mpl::identity<PassedCheck>,
mpl::identity<ConceptCheck<LastType>>>
{ };
}
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept {
private:
typedef typename _details::check_concept_impl<ConceptCheck, ModelTypes...>::type result_type;
public:
// the constexpr method assert produces shorter, fixed depth (2) error messages than a nesting assert in the trait solution
// the error message is not trahsed with the stack of variadic template recursion
constexpr static int apply() {
return result_type::printError();
}
};
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
template<typename BoolType = false_t>
constexpr static int printError () {
static_assert(BoolType::value, "Type is not a container model");
return 0;
}
};
and the usage:
check_concept<IsContainerCheck, std::vector<int>, std::vector<int>, float, int>::apply();
The solution is probably not the most elegant one but I it keeps the assert message short:
In file included from ../main.cpp:4:0:
../constraint.check.hpp: In instantiation of ‘static constexpr int IsContainerCheck::printError() [with BoolType = std::integral_constant; ContainerType = float]’:
../constraint.check.hpp:61:34: required from ‘static constexpr int check_concept::apply() [with ConceptCheck = IsContainerCheck; ModelTypes = {std::vector >, std::vector >, float, int}]’
../main.cpp:25:83: required from here
../constraint.check.hpp:74:3: error: static assertion failed: Type is not a container model
static_assert(BoolType::value, "Type is not a container model");
The assert is issued in a constexpr method after the check_concept template specialization has been done. Embedding the static assert directly into the template class definition would drag the whole check_concept_impl recursion stack into the error message.
So changing the IsContainerCheck trait to something like (rest of the changes omitted for readibility):
template<typename ContainerType>
struct IsContainerCheck
{
static_assert(is_container<ContainerType>::type::value, "Type is not a container model");
};
would yield an error
../constraint.check.hpp: In instantiation of ‘struct IsContainerCheck’:
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, float, int>’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl >, float, int>, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, std::vector >, float, int>’
../constraint.check.hpp:53:84: required from ‘struct check_concept >, std::vector >, float, int>’
../main.cpp:25:81: required from here
../constraint.check.hpp:72:2: error: static assertion failed: Type is not a container model
static_assert(is_container::type::value, "Type is not a container model");
As you can see each recursive eval_if call is emended in the error description which is bad because it makes the error message dependent from the amount and type of template parameters.